107 votes

Comment puis-je exécuter un script PHP en arrière-plan après la soumission d'un formulaire?

Problème
J'ai un formulaire qui, lorsqu'il est soumis, va exécuter le code de base pour traiter les informations présentées et les insérer dans une base de données pour l'affichage sur un site web notification. En plus, j'ai une liste de personnes qui ont signé jusqu'à recevoir ces notifications par e-mail et SMS. Cette liste est trivial comme le moment (seulement en poussant environ 150), mais il suffit à la cause qu'il faut plus d'une minute pour parcourir l'ensemble de la table d'abonnés et d'envoyer 150+ e-mails. (Les e-mails sont envoyés individuellement comme demandé par les administrateurs du système de notre serveur de courrier électronique en raison de la masse des politiques de messagerie.)

Pendant ce temps, la personne qui a publié l'alerte va s'asseoir sur la dernière page du formulaire de près d'une minute sans le renforcement positif que leur avis est posté. Cela conduit à d'autres problèmes potentiels, tous les possibles solutions que je ressens sont moins qu'idéales.

  1. Tout d'abord, l'affiche pourrait penser que le serveur est à la traîne et cliquez sur le bouton "Soumettre" à nouveau, provoquant le script de recommencer ou exécuté deux fois. J'ai pu résoudre ce problème en utilisant JavaScript pour désactiver le bouton et remplacer le texte-à-dire comme quelque chose de " Processing...", cependant ce n'est pas l'idéal, car l'utilisateur sera toujours bloqué sur la page de la durée de l'exécution du script. (Aussi, si JavaScript est désactivé, ce problème existe toujours.)

  2. Deuxièmement, l'affiche peut fermer l'onglet ou le navigateur prématurément après la soumission du formulaire. Le script va garder en cours d'exécution sur le serveur jusqu'à ce qu'il tente d'écrire au navigateur, cependant, si l'utilisateur accède à une page au sein de notre domaine (alors que le script est encore en cours d'exécution), le navigateur se bloque au chargement de la page jusqu'à ce que le script est terminé. (Cela n'arrive que lorsqu'un onglet ou la fenêtre du navigateur est fermé et non la totalité de l'application de navigateur.) Toujours, ce n'est pas l'idéal.

(Possible) De La Solution
J'ai décidé, je veux sortir de la "e-mail" partie du script dans un fichier séparé, je peux appeler après que l'avis a été posté. J'ai d'abord pensé à mettre cela sur la page de confirmation après la notification a bien été posté. Toutefois, l'utilisateur ne saura pas ce script est en cours d'exécution et les éventuelles anomalies ne sera pas évident pour eux; Ce script ne peut pas échouer.

Mais, si je peux utiliser ce script comme un processus d'arrière-plan? Donc, ma question est la suivante: Comment puis-je exécuter un script PHP pour déclencher comme un service d'arrière-plan et l'exécuter de manière complètement indépendante de ce que l'utilisateur a fait au niveau du formulaire?

EDIT: Ce ne peut pas être cron ed. Il doit s'exécuter à l'instant que le formulaire est soumis. Ces sont de haute priorité de notifications. En outre, le système les administrateurs de l'exécution de nos serveurs interdire crons de courir tous les plus fréquemment que 5 minutes.

95voto

Michael Irigoyen Points 11056

Faire quelques essais avec exec et shell_exec j'ai découvert une solution qui a fonctionné parfaitement! Je choisis d'utiliser shell_exec donc je peux me connecter tous les processus de notification qui se passe (ou ne pas). (shell_exec revient à la chaîne et c'était plus facile que d'utiliser exec, de l'affectation de la sortie d'une variable et de l'ouverture d'un fichier pour écrire.)

Je suis l'aide de la ligne suivante pour appeler le script email:

shell_exec("/path/to/php /path/to/send_notifications.php '".$post_id."' 'alert' >> /path/to/alert_log/paging.log &");

Il est important de noter l' & à la fin de la commande (comme l'a fait remarquer @netcoder). Cette commande UNIX exécute un processus en arrière-plan.

Les variables supplémentaires entouré de guillemets simples après le chemin d'accès au script, sont fixés $_SERVER['argv'] variables que je peux appeler dans mon script.

Le script email puis les sorties de mon fichier journal à l'aide de l' >> et va afficher quelque chose comme ceci:

[2011-01-07 11:01:26] Alert Notifications Sent for http://alerts.illinoisstate.edu/2049 (SCRIPT: 38.71 seconds)
[2011-01-07 11:01:34] CRITICAL ERROR: Alert Notifications NOT sent for http://alerts.illinoisstate.edu/2049 (SCRIPT: 23.12 seconds)

20voto

netcoder Points 31874

Sur les serveurs Linux / Unix, vous pouvez exécuter un travail en arrière-plan à l'aide de proc_open :

 $descriptorspec = array(
   array('pipe', 'r'),               // stdin
   array('file', 'myfile.txt', 'a'), // stdout
   array('pipe', 'w'),               // stderr
);

$proc = proc_open('php email_script.php &', $descriptorspec, $pipes);
 

Le & étant le bit important ici. Le script continuera même si le script original est terminé.

8voto

Simon Points 1176

PHP exec("php script.php") peut le faire.

À partir du Manuel:

Si un programme est démarré avec ce fonction dans l'ordre pour continuer cours d'exécution en arrière-plan, la sortie le programme doit être redirigé vers une fichier ou d'un autre flux de sortie. À défaut cela entraînera PHP pour accrocher jusqu'à ce que l'exécution du programme se termine.

Donc, si vous rediriger la sortie vers un fichier journal (ce qui est une bonne idée de toute façon), votre script d'appel ne sera pas suspendu email et votre script sera exécuté en bg.

4voto

Ivan Buttinoni Points 2360

Comme je sais que vous ne pouvez pas le faire de manière simple (voir la fourche exec etc (ne fonctionne pas sous windows), peut-être vous pouvez inverser la démarche, utiliser l'arrière-plan du navigateur affichant le formulaire en ajax, donc si le post encore le travail que vous avez pas de temps d'attente.
Cela peut aider, même si vous devez faire une longue élaboration.

Sur l'envoi de mail, c'est toujours vous suggérons d'utiliser un spouleur, peut être un local et rapidement un serveur smtp qui acceptent de vos demandes et de la bobine à la vraie MTA ou mettre le tout dans une DB, que d'utiliser un cron qui spool la file d'attente.
Le cron est peut-être sur une autre machine en appelant le spouleur externe url:

* * * * * wget -O /dev/null http://www.example.com/spooler.php

3voto

Ian Points 3250

Le travail de fond de cron semble être une bonne idée pour cela.

Vous aurez besoin d’un accès ssh à la machine pour exécuter le script en tant que cron.

$ php scriptname.php pour l'exécuter.

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