sey*_*ulu 10 php mysql events asynchronous yii
我想知道是否有可能在操作呈现视图时从其中一个操作异步调用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));
}
Run Code Online (Sandbox Code Playgroud)
我试图在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 <a href='{$url}'>{$url}</a>.";
$message->to_user_id = $trainee->id;
$message->save();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)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));
}
}
}
}
Run Code Online (Sandbox Code Playgroud)准备好的陈述
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();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)我还检查了以下网站(我只允许发布两个链接)但是他们要么需要等待请求完成的动作,要么需要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 <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));
}
Run Code Online (Sandbox Code Playgroud)
尽管如此,如果有人可以发布一种异步调用函数的方法,那就太好了.
小智 4
通常,此类问题的解决方案是在系统中集成消息总线。您可以考虑像Beanstalkd这样的产品。这需要在您的服务器上安装软件。我想这个建议将被称为“使用外部库”。
如果您可以访问部署服务器并且可以添加 cronjob(或者系统管理员可以),您可以考虑使用 cronjob 对脚本进行 php-cli 调用,该脚本从数据库中的作业队列读取作业,该队列由控制器填充方法。
如果您无法在正在运行的服务器上安装软件,您可以考虑使用Iron.io等 SAAS 解决方案来为您托管总线功能。Iron.io 使用所谓的推送队列。通过推送队列,消息总线主动向注册的侦听器执行带有消息内容的请求(推送)。这可能会起作用,因为它不需要您执行卷曲请求。
如果以上都不可行,那么您就束手无策了。另一篇与该主题非常相关的文章:Scalable, Delayed PHP Handling
| 归档时间: |
|
| 查看次数: |
4267 次 |
| 最近记录: |