Если вы не можете смягчить необходимость сделать это, как подсказывает догматик, тогда читайте дальше.
Итак, у вас есть (потенциально) долгосрочное задание, которое вы хотите выполнить, и вы не хотите, чтобы пользователь ждал.
Поскольку код PHP, выполняемый вашим пользователем, происходит во время запроса, который был запущен Apache, любой выполняемый код будет останавливать этот запрос до его завершения (если вы не достигнете тайм-аута запроса Apache).
Если вышеперечисленное неприемлемо для вашего приложения, вам нужно будет запустить PHP с помощью запроса Apache (т. Е. Из командной строки).
В отношении удобства использования на данном этапе имеет смысл уведомить пользователя о том, что вы обрабатываете данные в фоновом режиме. Все, от сообщения, сообщающего им, что они могут позже вернуться к вращающейся строке прогресса, которая опрашивает ваше приложение через ajax, чтобы обнаружить завершение работы.
Самый простой подход - иметь cronjob, который выполняет PHP-скрипт (т.е. оболочку CakePHP) через некоторый интервал (как минимум, это один раз в минуту). Здесь вы можете выполнять такие задачи в фоновом режиме.
Однако некоторые проблемы возникают с фоновыми заданиями. Как вы знаете, когда они потерпели неудачу? Как узнать, когда нужно повторить попытку? Что, если он не завершится в интервале cron ... произойдет ли состояние гонки?
Надлежащей, но более сложной настройкой было бы использование системы работы / очереди сообщений. Они позволяют обрабатывать вышеуказанные проблемы более изящно, но, как правило, требуют запуска фонового демона на сервере, чтобы перехватывать и обрабатывать любые входящие задания.
Как это работает, в своем коде (когда пользователь регистрируется) вы вставляете задание в очередь. Демон очереди мгновенно забирает задание (оно не выполняется с интервалом, поэтому всегда ожидает) и передает его рабочему процессу (например, оболочке CakePHP). Это мгновенно, и - если вы скажете это - он знает, сработало ли это, он знает, не сработало ли это, он может повторить попытку, если хотите, и случайно не выполнил одно и то же задание дважды.
Доступно несколько таких типов, как Beanstalkd , dropr , Gearman , RabbitMQ и т. Д. несколько плагинов CakePHP (различного возраста), которые могут помочь:
У меня был опыт использования CakePHP как с Beanstalkd (+ библиотека PHP Pheanstalk ), так и с плагином CakePHP Queue (первый выше). Я должен отдать должное Beanstalkd (написано на C) за то, что он очень легкий, простой и быстрый. Однако, что касается разработки CakePHP, я обнаружил, что плагин быстрее запускается и работает, потому что:
- Плагин поставляется со всем кодом PHP, необходимым для начала работы. В Beanstalkd вам нужно написать больше кода (например, PHP-демон, который опрашивает очередь в поисках работы)
- Инфраструктура сервера Beanstalkd становится более сложной. Мне пришлось установить несколько экземпляров
beanstalkd
для dev / test / prod и установить supervisord
, чтобы следить за процессами).
- Разработка / тестирование немного проще, так как это автономное решение CakePHP + MySQL. Вам просто нужно набрать
cake queue add user signup
и cake queue runworker
.