Вызов асинхронного метода 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));
}

Проблема

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

Теперь я ищу способ асинхронного выполнения запроса, чтобы отправитель увидел свой ответ как можно быстрее, в то время как запрос выполняется в фоновом режиме, подобно делегатам или событиям C #.

Решения, которые я нашел в Google, выполняли асинхронный запрос (s)в ходе действия контроллера, но все, что я хочу сделать, это асинхронно запустить метод контроллера, и действие должно было ] подождите , пока запрос (с)не будет завершен.

Попытка

Я испробовал следующие методы, но запрос по-прежнему выполняется медленно для моих тестовых данных о 1500 пользователях.

  • Yii ActiveRecord

    if ($vacancy->save()) {                
        if($vacancy->is_active == 1) {
            $url = Yii::app()->createUrl('vacancies/view',array('id'=>$model->id));
            $trainees = YumUser::getUsersByRole('Trainees');
            if($trainees!=null) {
                foreach($trainees as $trainee){
                    $message = new YumMessage;
                    $message->from_user_id = Yii::app()->user->id;
                    $message->title = 'Vacancy Notification: '.date('M j, Y');
                    $message->message = "A new vacancy has been posted at {$url}.";
                    $message->to_user_id = $trainee->id;
                    $message->save();                
                }
            }
        }    
    }
    
  • Объекты доступа к данным Yii

    if ($vacancy->save()) {        
        if($vacancy->is_active == 1) {
            $url = Yii::app()->createAbsoluteUrl('vacancies/view',array('id'=>$model->id));
            $trainee_ids=Yii::app()->db->createCommand()->select('user_id')->from('trainee')->queryColumn();
            $fid=Yii::app()->user->id;
            $msg="A new vacancy has been posted at {$url}.";
            $ts = time();
            $tt = 'Vacancy Notification: '.date('M j, Y');
            if($trainee_ids!=null) {
                foreach($trainee_ids as $trainee_id){
                    Yii::app()->db->createCommand()
                      ->insert('message',array('timestamp'=>$ts,'from_user_id'=>$fid,'to_user_id'=>$tid,'title'=>$tt,'message'=>$msg));
                }
            }
        }
    }
    
  • Подготовленные отчеты

    if ($vacancy->save()) {                
        if($vacancy->is_active == 1) {
            $url = Yii::app()->createUrl('vacancies/view',array('id'=>$model->id));                    
            $trainee_ids=Yii::app()->db->createCommand()->select('user_id')->from('trainee')->queryColumn();
            $fu=Yii::app()->user->id;
            $msg="A new vacancy has been posted at {$url}.";
            $ts = time();
            $tt = 'Vacancy Notification: '.date('M j, Y');
            $sql="INSERT INTO message (timestamp,from_user_id,title,message,to_user_id) VALUES (:ts,:fu,:tt,:msg,:tu)";
            if($trainee_ids!=null) {
                foreach($trainee_ids as $trainee_id){
    
                    $command=Yii::app()->db->createCommand($sql);
                    $command->bindParam(":ts",$ts,PDO::PARAM_INT);
                    $command->bindParam(":fu",$fu,PDO::PARAM_INT);
                    $command->bindParam(":tt",$tt,PDO::PARAM_STR);
                    $command->bindParam(":msg",$msg,PDO::PARAM_STR);
                    $command->bindParam(":tu",$trainee_id,PDO::PARAM_INT);
    
                    $command->execute();
    
                }
            }
        }
    }
    

Исследования

Я также проверил следующие веб-сайты (Мне разрешено публиковать только две ссылки ), но они требуют действие, чтобы дождаться завершения запроса или потребовать curl (, к которому у меня нет доступа на сервере развертывания ), или нужна внешняя библиотека. Я надеялся на нативную реализацию PHP.

Изменить

Я смог значительно сократить время отклика, переписав свой запрос таким образом (переместив пользовательский цикл на уровень базы данных):

public function actionCreate() {
    $user=YumUser::model()->findByPk(Yii::app()->user->id);
    $model = new Vacancies;
    $model->corporate_id=$user->professional->institution->corporate->id;
    $model->date_posted=date('Y-m-d');
    $model->last_modified=date('Y-m-d H:i:s');

    if (isset($_POST['Vacancies'])) {
        $model->setAttributes($_POST['Vacancies']);
        if ($model->save()) {                
            if($model->is_active == 1) {
                $url = Yii::app()->createAbsoluteUrl('vacancies/view',array('id'=>$model->id));                    
                $fu=Yii::app()->user->id;
                $msg="A new vacancy has been posted at {$url}.";
                $ts = time();
                $tt = 'New Vacancy: '.$model->title;
                $sql='INSERT INTO message (timestamp,from_user_id,title,message,to_user_id) SELECT :ts,:fu,:tt,:msg,t.user_id FROM trainee t';
                Yii::app()->db->createCommand($sql)->execute(array(':ts'=>$ts,':fu'=>$fu,':tt'=>$tt,':msg'=>$msg));
            }                
            if (Yii::app()->getRequest()->getIsAjaxRequest())
                Yii::app()->end();
            else
                $this->redirect(array('view', 'id' => $model->id));
        }
    }
    $this->render('create', array( 'model' => $model));
}

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

10
задан Community 23 May 2017 в 12:32
поделиться