質問
アクションがビューをレンダリングしている間に、そのアクションの 1 つから 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# のデリゲートやイベントと同様の方法でクエリがバックグラウンドで実行されている間、投稿者はできるだけ短い時間で応答を確認できます。
私がグーグルアップしたソリューションは、コントローラーアクションの過程で非同期リクエストを実行しましたが、やりたいことはコントローラーのメソッドを非同期で実行することだけであり、アクションはリクエストが完了するまで待たなければなりませんでした。
試みた
次の方法を試しましたが、約 1500 人のユーザーのテスト データでは、クエリはまだ遅いです。
Yii アクティブレコード
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(); } } } }
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 <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)); } } } }
準備されたステートメント
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(); } } } }
リサーチ
次の Web サイトも確認しました (リンクを 2 つしか投稿できません) が、要求が完了するまで待機するアクションが必要であるか、curl が必要です (展開サーバーではアクセスできません)。外部ライブラリが必要です。ネイティブの PHP 実装を期待していました。
- PHP シミュレートされたマルチスレッド
- PHP でのマルチスレッド
- 非同期 PHP 呼び出し?
- 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 <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));
}
それにもかかわらず、関数を非同期的に呼び出す方法を誰かが投稿できればいいのですが。