PHP异步方法调用Yii框架 [英] PHP Asynchronous Method Call In The Yii Framework

查看:201
本文介绍了PHP异步方法调用Yii框架的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否是可能的异步从其操作之一调用的Yii控制器方法而动作呈现一个视图,留下来完成长时间运行操作的方法。我很想做类似下面的code和我不需要返回从结果 my_long_running_func

I want to know if it is possible to asynchronously invoke a Yii controller method from one of its actions while the action renders a view, leaving the method to complete a long running operation. I would love to do something like the code below and I don't need to return a result from 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中的控制器操作的职位空缺,并通知该职位有兴趣的用户。的问题是,它需要很长的时间来执行通知查询

Problem

I am trying to write a controller action in Yii that posts a vacancy and notifies interested subscribers of the post. The problem is that it takes a long time to execute the notification query.

现在我正在寻找一种方式来异步运行查询,以便海报看到他在短短的时间尽可能响应,同时查询在类似C#委托或事件的方式在后台运行。

Now I am searching for a way to asynchronously run the query so the poster sees his response in as little time as possible while the query runs in the background in a way similar to C# delegates or events.

我GOOGLE了这些解决方案进行的异步请求(S)的控制器动作的过程中,但所有我想做的是异步运行的控制器的方法和行动不得不的烧至的请求(S)的完成。

The solutions I googled up performed asynchronous request(s) during the course of the controller action but all I want to do is to run a method of the controller asynchronously and the action had to wait till the request(s) were completed.

我曾尝试以下方法,但查询是静止约1500个用户的我的测试数据缓慢。

I have tried the following methods but the query is still slow for my test data of about 1500 users.


  • Yii的ActiveRecord的

  • 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();                
            }
        }
    }    
}


  • Yii的数据访问对象

  • Yii Data Access Objects

    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));
                }
            }
        }
    }
    


  • prepared声明

  • Prepared Statements

    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();
    
                }
            }
        }
    }
    


  • 我还检查了以下网站(我只允许发布两个链接),但他们要么要求采取行动,等待完成请求或需要卷曲(我没有对部署的访问服务器)或需要外部库。我希望的是原始的PHP实现。

    I have also checked the following websites (I'm only allowed to post two links) but they either require the action to wait for the request to be completed or need curl (which I don't have access to on the deployment server) or need an external library. I was hoping for a native PHP implementation.

    • PHP Simulated Multi-Threading
    • Multithreading in php
    • Asynchronous PHP calls?
    • Asynchronous processing in PHP

    我能够通过重写这样我的查询(移动用户环路到数据库层)显着降低响应时间:

    I was able to decrease response time considerably by rewriting my query in this way (moving the user loop to the database layer):

    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));
    }
    

    尽管如此,这将是很好,如果有人可以张贴的方式来调用函数异步。

    Notwithstanding, it would be nice if someone could post a way to call functions asynchronously.

    推荐答案

    通常对于此类问题的解决将是一个消息总线系统中的集成。你可以考虑如 Beanstalkd 的产品。这需要在服务器上安装软件。
    我想这个建议将使用外部库来调用。

    Typically the solution for these kind of problems would be to integrate a message-bus in your system. You could consider a product like Beanstalkd. This requires installing software on your server. I suppose this suggestion would be called "using an external library".

    如果您可以访问部署服务器,你可以添加的cronjob(或MAYB一个系统管理员可以),你可以考虑一个cronjob,做一个PHP-CLI调用一个脚本,在数据库中的作业队列,其中充满阅读职位由控制器方法

    If you can access the deployment server and you can add cronjob (or mayb a sysadmin can) you could consider a cronjob that does a php-cli call to a script that reads jobs from a job queue in your database which is filled by the controller method.

    如果你不能,你正在运行,你可以考虑使用SaaS解决方案如 Iron.io 主办总线功能为您服务。 Iron.io是使用所谓的推送队列。随着推送队列中的消息总线积极执行一个请求(推)的注册听众消息内容。这可能工作,因为它不要求你做一个卷曲的请求。

    If you cannot install software on the server you're running you could consider using a SAAS solution like Iron.io to host the bus functionality for you. Iron.io is using what is called a push queue. With a push queue the message bus actively performs a request (push) to the registered listeners with the message content. This might work since it doesn't require you to do a curl request.

    如果以上都不是可能的;你的双手被缚。另一篇文章是关于这个问题很有关系:可扩展,延迟PHP处理

    If none of the above is possible; your hands are tied. Another post which is quite relevant on the subject: Scalable, Delayed PHP Processing

    这篇关于PHP异步方法调用Yii框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆