PHP асинхронный вызов метода в Yii Framework

вопрос

Я хочу знать, можно ли асинхронно вызывать метод контроллера Yii из одного из его действий, пока действие отображает представление, оставляя метод для завершения длительной операции. Я хотел бы сделать что-то вроде ниже код и мне не нужно возвращать результат из my_long_running_func.

public function actionCreate() {
    $model = new Vacancies;
    if (isset($_POST['Vacancies'])) {
        $model->setAttributes($_POST['Vacancies']);
        $model->save();
        //I wish :)
        call_user_func_async('my_long_running_func',$model);
    }
    $this->render('create', array( 'model' => $model));
}

3 ответов


Как правило, решением таких проблем будет интеграция шины сообщений в вашу систему. Вы можете рассмотреть такой продукт, как Beanstalkd. Это требует установки программного обеспечения на сервере. Я полагаю, что это предложение будет называться "использование внешней библиотеки".

Если вы можете получить доступ к серверу развертывания, и вы можете добавить cronjob (или, возможно, системный администратор может) , вы можете рассмотреть cronjob, который выполняет вызов php-cli скрипту, который читает задания из задания очередь в вашей базе данных, которая заполняется методом контроллера.

Если вы не можете установить программное обеспечение на сервере, вы можете рассмотреть возможность использования решения SAAS, как железо.Ио разместить функциональность шины для вас. Железо.io использует то, что называется push queue. С помощью очереди push шина сообщений активно выполняет запрос (push) к зарегистрированным слушателям с содержимым сообщения. Это может сработать, так как вам не нужно делать завиток запрос.

Если ничего из вышеперечисленного невозможно, ваши руки связаны. Еще один пост, который весьма актуален по данной теме:масштабируемая, отложенная обработка PHP


Я бы попробовал это, хотя я не на 100% , что Yii будет работать правильно, но его относительно просто и стоит пойти:

public function actionCreate() {
    $model = new Vacancies;
    if (isset($_POST['Vacancies'])) {
        $model->setAttributes($_POST['Vacancies']);
        $model->save();
        //I wish :)
    }

    HttpResponse::setContentType('text/html');
    HttpResponse::setData($this->render('create', array( 'model' => $model), true);
    HttpResponse::send();

    flush(); // writes the response out to the client

    if (isset($_POST['Vacancies'])) {
        call_user_func_async('my_long_running_func',$model);
    }
}

вот совершенно другой тип предложения. Как насчет регистрации события onEndRequest, которое запускается функция конца() CWebApplication?

public function end($status=0, $exit=true)
{
    if($this->hasEventHandler('onEndRequest'))
        $this->onEndRequest(new CEvent($this));
    if($exit)
        exit($status);
}

вам нужно будет зарегистрироваться для события и выяснить, как передать вашу модель каким-то образом, но код будет правильно работать после того, как все данные будут сброшены в браузер ...