70 votes

Appel d'un script PHP à partir d'un trigger MySQL

Existe-t-il un moyen d'invoquer une page / fonction PHP lorsqu'un enregistrement est inséré dans une table de base de données MySQL ? Nous n'avons pas le contrôle de la procédure d'insertion des enregistrements. Existe-t-il un mécanisme de déclenchement permettant de rappeler un script PHP ?

0 votes

Peut-être que cela vous aidera : stackoverflow.com/questions/40025369/

34voto

Pascal MARTIN Points 195780

Le déclencheur est exécuté sur le serveur MySQL, et non sur le serveur PHP (même si les deux sont sur la même machine).

Je dirais donc que ce n'est pas tout à fait possible - du moins pas simplement.

Pourtant, en considérant cette entrée de la FAQ MySQL sur les déclencheurs :

23.5.11 : Les déclencheurs peuvent-ils appeler une application externe via un UDF ?

Oui. Par exemple, un déclencheur pourrait invoquer le sys_exec() UDF disponible ici : https://github.com/mysqludf/lib_mysqludf_sys#readme

Donc, il pourrait y avoir un moyen via une fonction UDF qui lancerait l'exécutable php/script. Pas si facile, mais cela semble possible ;-)

6 votes

Ou qu'il pourrait appeler curl ?

1 votes

Si php et/ou le script n'est pas sur le même serveur physique, cela pourrait être une solution aussi, oui.

0 votes

Martin tips est plutôt cool... Mais appeler PHP de cette façon n'est pas un bon choix de conception. Vous devriez le reconsidérer

27voto

Mike E. Points 211

Un ami et moi avons trouvé comment appeler l'UDF sys_eval de Bernardo Damele, mais la solution n'est pas aussi élégante que je le voudrais. Voici ce que nous avons fait :

  1. Puisque nous utilisons Windows, nous avons dû compiler la bibliothèque UDF pour Windows en utilisant Instructions de Roland Bouman et les installer sur notre serveur MySQL.
  2. Nous avons créé une procédure stockée qui appelle sys_eval.
  3. Nous avons créé un déclencheur qui appelle la procédure stockée.

Code de procédure stockée :

DELIMITER $$
CREATE PROCEDURE udfwrapper_sp
(p1   DOUBLE,
 p2   DOUBLE,
 p3 BIGINT)
BEGIN
 DECLARE cmd CHAR(255);
 DECLARE result CHAR(255);
 SET cmd = CONCAT('C:/xampp/php/php.exe -f "C:/xampp/htdocs/phpFile.php" ', p1, ' ', p2, ' ', p3);
 SET result = sys_eval(cmd);
END$$;

Code de déclenchement :

CREATE TRIGGER udfwrapper_trigger AFTER INSERT ON sometable
FOR EACH ROW
CALL udfwrapper_sp(NEW.Column1, NEW.Column2, NEW.Column3);

Je ne suis pas ravi d'avoir une procédure stockée, et je ne sais pas si cela crée des frais supplémentaires, mais cela fonctionne. Chaque fois qu'une ligne est ajoutée à une table, le déclencheur se déclenche.

17voto

FractalizeR Points 12887

Cela devrait être considéré comme un très mauvaise pratique de programmation pour appeler du code PHP à partir d'un déclencheur de base de données. Si vous nous expliquez la tâche que vous essayez de résoudre en utilisant ces astuces "folles", nous pourrons peut-être vous fournir une solution satisfaisante.

AJOUTÉ LE 19.03.2014 :

J'aurais dû ajouter un raisonnement plus tôt, mais je n'ai trouvé le temps de le faire que maintenant. Merci à @cmc pour une remarque importante. Ainsi, les déclencheurs PHP ajoutent les complexités suivantes à votre application :

  • Ajoute un certain degré de problèmes de sécurité à l'application (appels PHP script externes, configuration des autorisations, probablement configuration SELinux etc) comme le dit @Johan.

  • Ajoute un niveau de complexité supplémentaire à votre application (pour comprendre le fonctionnement de la base de données, vous devez maintenant connaître à la fois SQL et PHP, et pas seulement SQL) et vous devrez également déboguer PHP, et pas seulement SQL.

  • Ajoute un point d'échec supplémentaire à votre application (mauvaise configuration de PHP par exemple), qui doit être diagnostiqué également (je pense que le trigger doit contenir un code de débogage qui enregistrera quelque part tous les appels infructueux de l'interpréteur PHP et leurs raisons).

  • Ajoute un point supplémentaire d'analyse des performances. Chaque appel PHP est coûteux, puisqu'il faut lancer l'interpréteur, compiler script en bytecode, l'exécuter, etc. Donc chaque requête impliquant ce déclencheur s'exécutera plus lentement. Et parfois, il sera difficile d'isoler les problèmes de performance de la requête puisque EXPLAIN ne vous dit rien sur la requête qui est plus lente à cause de la performance de la routine du trigger. Et je ne suis pas sûr de la façon dont le temps de déclenchement est transféré dans le journal des requêtes lentes.

  • Ajoute quelques problèmes aux tests d'application. SQL peut être testé assez facilement. Mais pour tester SQL + les déclencheurs PHP, vous devrez faire preuve d'un certain savoir-faire.

8 votes

Pourquoi ? Il semble que cela pourrait être très fonctionnel. Par exemple, un php script insère sur un serveur de db distant, le serveur pourrait lancer un php script local pour faire quelque chose sur cette machine.

0 votes

Au moins parce que cela ne peut pas être fait assez vite. Les déclencheurs doivent s'exécuter aussi vite que possible. Le code PHP est un mauvais candidat pour cette tâche. De plus, la connexion entre la base de données et PHP est faible, ce qui affaiblit l'intégrité de la base de données.

35 votes

Je ne pense pas que ce soit une "très mauvaise pratique de programmation"... c'est juste une manière non conventionnelle. Dans mon cas, j'ai besoin d'une réponse "en temps réel" de MySQL->PHP->Javascript (en utilisant des web sockets HTML5). Comme le serveur ws et le serveur web fonctionnent sur des ports différents, je n'ai pas d'autre moyen "simple" d'y parvenir. (et...) Interroger la base de données chaque seconde me semble peu pratique car les données ne changent pas chaque seconde (elles peuvent ne pas changer en quelques heures).

7voto

phazei Points 1007

Je pensais à cette question exacte pour un cas avec une longue interrogation où je ne voulais pas que le php script ait à interroger continuellement la db. L'interrogation devrait être faite quelque part, la mémoire serait probablement le mieux. Donc, si d'une manière ou d'une autre, le déclencheur pourrait mettre l'info dans quelque chose comme memcache, puis php pourrait sonder que serait beaucoup moins intensif dans l'ensemble. Il faut juste une méthode pour que mysql utilise memcache. Peut-être dans une variable prédéfinie avec un identifiant d'utilisateur spécifique. Une fois que les données sont récupérées, php pourrait réinitialiser la variable jusqu'à ce que la base de données la remette en place. Je ne suis pas sûr des problèmes de timing. Peut-être une deuxième variable pour stocker la clé précédente sélectionnée.

5voto

Lance Rushing Points 4376

J'ai trouvé ça :

http://forums.mysql.com/read.php?99,170973,257815#msg-257815

DELIMITER $$
CREATE TRIGGER tg1 AFTER INSERT ON `test`
FOR EACH ROW
BEGIN
\! echo "php /foo.php" >> /tmp/yourlog.txt
END $$
DELIMITER ;

13 votes

\La commande : n'est exécutée qu'une seule fois (sur CREATE TRIGGER). Elle ne s'exécute pas lors de l'insertion.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X