Asynchroner PHP-Methodenaufruf im Yii-Framework

Frage

Ich möchte wissen, ob es möglich ist, eine Yii-Controller-Methode über eine ihrer Aktionen asynchron aufzurufen, während die Aktion eine Ansicht rendert, sodass die Methode einen Vorgang mit langer Laufzeit abschließt. Ich würde gerne so etwas wie den folgenden Code machen und ich muss kein Ergebnis von zurückgebenmy_long_running_func.

<code>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));
}
</code>
Problem

Ich versuche, eine Controller-Aktion in Yii zu schreiben, die eine freie Stelle veröffentlicht und interessierte Abonnenten über die Stelle benachrichtigt. Das Problem ist, dass die Ausführung der Benachrichtigungsabfrage sehr lange dauert.

Jetzt suche ich nach einer Möglichkeit, die Abfrage asynchron auszuführen, damit das Poster seine Antwort in so kurzer Zeit wie möglich sieht, während die Abfrage im Hintergrund ausgeführt wird, ähnlich wie bei C # -Delegierten oder -Ereignissen.

Die Lösungen, die ich gegoogelt habe, wurden ausgeführtasynchrone Anfrage (n) im laufe der controlleraktion möchte ich aber nur eine methode des controller asynchron ausführen und die aktion musstewarten bis zumAnfrage (n) wurden fertiggestellt.

Versucht

Ich habe die folgenden Methoden ausprobiert, aber die Abfrage ist für meine Testdaten von etwa 1500 Benutzern immer noch langsam.

Yii ActiveRecord

<code>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 <a href='{$url}'>{$url}</a>.";
                $message->to_user_id = $trainee->id;
                $message->save();                
            }
        }
    }    
}
</code>

Yii Datenzugriffsobjekte

<code>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 <a href='{$url}'>{$url}</a>.";
        $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));
            }
        }
    }
}
</code>

Vorbereitete Aussagen

<code>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 <a href='{$url}'>{$url}</a>.";
        $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();

            }
        }
    }
}
</code>
Forschung

Ich habe auch die folgenden Websites überprüft (ich darf nur zwei Links posten), aber entweder muss die Aktion warten, bis die Anforderung abgeschlossen ist, oder ich muss mich einrollen (auf die ich auf dem Bereitstellungsserver keinen Zugriff habe) oder brauche eine externe Bibliothek. Ich hatte auf eine native PHP-Implementierung gehofft.

PHP simuliertes MultithreadingMultithreading in PHPAsynchrone PHP-Aufrufe?Asynchrone Verarbeitung in PHPBearbeiten

Ich konnte die Antwortzeit erheblich verkürzen, indem ich meine Abfrage auf diese Weise umschrieb (indem ich die Benutzerschleife in die Datenbankebene verschob):

<code>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 <a href='{$url}'>{$url}</a>.";
                $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));
}
</code>

Trotzdem wäre es schön, wenn jemand eine Möglichkeit posten könnte, Funktionen asynchron aufzurufen.

Antworten auf die Frage(3)

Ihre Antwort auf die Frage