Выполнить код после завершения HTTP-запроса в PHP? - PullRequest
4 голосов
/ 16 ноября 2008

PHP предоставляет механизм для регистрации функции выключения:

register_shutdown_function('shutdown_func');

Проблема в том, что в последних версиях PHP эта функция все еще выполняется во время запроса.

У меня есть платформа (в Zend Framework, если это имеет значение), где любой фрагмент кода в запросе может зарегистрировать запись для входа в базу данных. Вместо того чтобы иметь тонны отдельных операторов вставки в запросе, что замедляет работу страницы, я ставлю их в очередь для вставки в конце запроса. Я хотел бы иметь возможность сделать это после того, как HTTP-запрос завершен с пользователем, поэтому продолжительность времени для входа или выполнения каких-либо других задач очистки не влияет на предполагаемое время загрузки страницы пользователем.

Есть ли в PHP встроенный метод для этого? Или мне нужно настроить какую-то схему пространства совместно используемой памяти с внешним процессом и подать сигнал этому процессу для ведения журнала?

Ответы [ 4 ]

4 голосов
/ 16 ноября 2008

Если вас действительно беспокоит время вставки MySQL, вы, вероятно, обращаетесь к симптомам, а не к их причине.

Например, если ваш процесс PHP / Apache выполняется после того, как пользователь получает свой HTML, ваш процесс PHP / Apache все еще заблокирован в этом запросе. Так как он занят, если приходит другой запрос, Apache должен разветвить другой поток, выделить ему больше памяти, открыть дополнительные соединения с базой данных и т. Д.

Если у вас возникли проблемы с производительностью, вам нужно убрать тяжелую нагрузку с выполнения PHP / Apache. Если у вас много задач по очистке, вы сжигаете драгоценные процессы Apache.

Я бы рассмотрел запись ваших записей в файл и загрузил их в вашу базу данных crontab. Если у вас есть другие тяжелые задачи, используйте систему очередей / обработки заданий для выполнения работы вне диапазона.

1 голос
/ 16 ноября 2008

Помимо register_shutdown_function () нет встроенных методов для определения момента выхода из скрипта. Однако Zend Framework имеет несколько хуков для запуска кода в определенных точках процесса отправки. Для ваших требований наиболее релевантными были бы переадресация действий контроллера , которая происходит сразу после отправки действия, и событие dispatchLoopShutdown для посредника плагинов контроллера. *

Вы должны прочитать руководство, чтобы определить, что подойдет вам лучше.

РЕДАКТИРОВАТЬ: Я думаю, я не понял полностью. Из этих хуков вы могли бы раскошелиться на текущий процесс в той или иной форме. В PHP есть несколько способов ветвления процессов, которые вы можете прочитать в руководстве в разделе Выполнение программы . Я бы посоветовал перейти к расширению pcntl - прочитайте это сообщение в блоге , чтобы увидеть пример разветвления дочерних процессов для запуска в фоновом режиме.

0 голосов
/ 16 ноября 2008

Это может быть немного хакерским на ваш вкус, но это будет эффективный и простой обходной путь.

Вы можете создать «очередь», управляемую выбранной вами БД, и сначала сохранить запрос в таблице очередей в базе данных, а затем вывести iframe, который приведет к сценарию, который будет запускать инструкции, совпадающие с queue_id в вашей базе данных.

например:

<?php
mysql_query('INSERT INTO queue ('instructions') VALUES ('something would go here');
echo('<iframe src="/yourapp/execute_queue/id?' . mysql_insert_id() . '" />');
?>

и кадр будет делать что-то вроде

например:

<?php
$result = mysql_query('SELECT instructions FROM queue WHERE id = ' . $_GET['id']);
// From here, simply execute some instruction based on the "instructions" field, then delete the instruction from the database.
?>

Как я уже сказал, я вижу, как вы можете считать этот хакер, но фрейм будет загружаться независимо от родительской страницы, поэтому он достигнет того, что вы хотите, без запуска какого-либо другого приложения в фоновом режиме.

Надеюсь, это, по крайней мере, указывает вам правильное направление.

Ура!

0 голосов
/ 16 ноября 2008

Комментарии к блогу этого случайного парня звучат похоже на то, что вы хотите. Если этот трюк с заголовком не работает, один из комментариев в этом блоге предлагает exec() использовать отдельный PHP-скрипт для запуска в фоновом режиме, если конфигурация вашего веб-хоста допускает такое.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...