Phalcon学习笔记之分发器和事件管理器

Phalcon启动之后,会通过router路由器将URL解析,然后传递给dispatcher分发器,分发器会找到对应的Module/Controller/Action并执行,执行中会输出到view视图发送给客户端。

简单情况下分发器不需要特殊的配置,router的解析已经足够,一般来讲,只有在判断用户权限的时候才需要特殊处理

$di->set('dispatcher', function () {
            $dispatcher = new \Phalcon\Mvc\Dispatcher();
 
            //Attach a event listener to the dispatcher
            $eventManager = new \Phalcon\Events\Manager();
            $eventManager->attach('dispatch:beforeDispatch', new \SecurityPlugin(__CLASS__));
 
            $dispatcher->setEventsManager($eventManager);
            $dispatcher->setDefaultNamespace('Multiple\Entrance\Controllers\\');
            return $dispatcher;
        });

实际上Phalcon内建有事件机制,在Phalcon的很多类中都有事件接口,通过对事件接口的重新定义并挂载事件管理器,可以让个各类针对不同的情况在程序执行的特殊阶段做出不同的反映,比如跳转回主页之类。


\Phalcon\Events\Manager类通过attach函数的第一个参数定义流程控制类的某个特殊事件,通过第二个参数定义对应的行为,然后在流程控制对象中使用setEventsManager函数挂上这个事件控制器类,就可以在特定的事件发生时,调用事件控制器定义的行为,如果行为执行正常会返回程序主线,如果行为执行之后跳出了流程,就不会返回了。

常见的被视为跳出流程的标志有:1)返回false;2)重定向;3)强行中止;4)抛出异常

如果返回null或者true则会返回主线继续执行。

也就是说attach函数的第2个参数其实才是主要问题。实际上笔者的习惯是把用户权限判定放在那里。

对于分发器而言,内建有一些事件定义。对于其他的类,也有事件定义,可以参考各个类的官方手册。

Event Name    Triggered    Can stop operation?
beforeDispatchLoop    Triggered before enter in the dispatch loop. At this point the dispatcher don’t know if the controller or the actions to be executed exist. The Dispatcher only knows the information passed by the Router.    Yes
beforeDispatch    Triggered after enter in the dispatch loop. At this point the dispatcher don’t know if the controller or the actions to be executed exist. The Dispatcher only knows the information passed by the Router.    Yes
beforeExecuteRoute    Triggered before execute the controller/action method. At this point the dispatcher has been initialized the controller and know if the action exist.    Yes
afterExecuteRoute    Triggered after execute the controller/action method. As operation cannot be stopped, only use this event to make clean up after execute the action    No
beforeNotFoundAction    Triggered when the action was not found in the controller    Yes
beforeException    Triggered before the dispatcher throws any exception    Yes
afterDispatch    Triggered after execute the controller/action method. As operation cannot be stopped, only use this event to make clean up after execute the action    Yes
afterDispatchLoop    Triggered after exit the dispatch loop    No


来看一个稍微复杂点的事件管理器,它可以在找不到对应的Controller/Action时,做出合适的处理,不让用户看到难看的404错误

$di->setShared('dispatcher', function() {
 
    //Create/Get an EventManager
    $eventsManager = new Phalcon\Events\Manager();
 
    //Attach a listener
    $eventsManager->attach("dispatch", function($event, $dispatcher, $exception) {
 
        //The controller exists but the action not
        if ($event->getType() == 'beforeNotFoundAction') {
            $dispatcher->forward(array(
                'controller' => 'index',
                'action' => 'show404'
            ));
            return false;
        }
 
        //Alternative way, controller or action doesn't exist
        if ($event->getType() == 'beforeException') {
            switch ($exception->getCode()) {
                case Phalcon\Dispatcher::EXCEPTION_HANDLER_NOT_FOUND:
                case Phalcon\Dispatcher::EXCEPTION_ACTION_NOT_FOUND:
                    $dispatcher->forward(array(
                        'controller' => 'index',
                        'action' => 'show404'
                    ));
                    return false;
            }
        }
    });
 
    $dispatcher = new Phalcon\Mvc\Dispatcher();
 
    //Bind the EventsManager to the dispatcher
    $dispatcher->setEventsManager($eventsManager);
 
    return $dispatcher;
});


分发器的另外一个用途是让我们从一个Controller/Action跳转到另一个Controller/Action

<?php
 
class PostsController extends \Phalcon\Mvc\Controller
{
 
    public function indexAction()
    {
 
    }
 
    public function saveAction($year, $postTitle)
    {
 
        // .. store some product and forward the user
 
        // Forward flow to the index action
        $this->dispatcher->forward(array(
            "controller" => "post",
            "action" => "index"
        ));
    }
 
}

请记住,forward和HTTP重定向不一样,虽然他们显示了相同的结果。forward不刷新当前页面,所有的重定向都发生在一个单一的请求中,而HTTP重定向则需要完成两个请求。


另外在多Module程序中,forward不能跳到另一个Module,而HTTP重定向可以。这个时候使用下面的代码实现跳转

$this->response->redirect('entrance/index/login');


forward还有一些用法

// Forward flow to another action in the current controller
$this->dispatcher->forward(array(
    "action" => "search"
));
 
// Forward flow to another action in the current controller
// passing parameters
$this->dispatcher->forward(array(
    "action" => "search",
    "params" => array(1, 2, 3)
));
 
// Forward flow to another action in the current controller
// passing parameters
$this->dispatcher->forward(array(
    "action" => "search",
    "params" => array(1, 2, 3)
));

另外还可以通过getParam函数获取一些URL的信息
// Get the post's title passed in the URL as parameter
        $title = $this->dispatcher->getParam("title");
 
        // Get the post's year passed in the URL as parameter
        // also filtering it
        $year = $this->dispatcher->getParam("year", "int");

这些信息可以让程序做出针对性的反应

--------------------- 
作者:silent_missile 
来源:CSDN 
原文:https://blog.csdn.net/silent_missile/article/details/46560361 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值