问题
我想知道是否可以在操作呈现视图时从其操作之一异步调用 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(); } } } }
研究
我还检查了以下网站(我只允许发布两个链接),但它们要么需要等待请求完成的操作,要么需要 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));
}
尽管如此,如果有人可以发布一种异步调用函数的方法,那就太好了。