2014-01-23 85 views
13

我是否正确理解在执行$this->dispatcher->forward()$this->response->redirect()之后,我需要手动确保其余代码不会被执行?像下面,或者我错过了什么?Phalcon重定向和转发

public function signinAction() 
{ 
    if ($this->isUserAuthenticated()) 
    { 
     $this->response->redirect('/profile'); 
     return; 
    } 

    // Stuff if he isn't authenticated… 
} 

回答

24

将近一年的使用尔康超出其能力的铁杆项目的工作后,我想澄清一些事情并回答我自己的问题。要了解如何正确执行重定向和转发,您需要了解一些有关如何运行Dispatcher::dispatch方法的信息。

看看代码here,尽管它对我们大多数人来说都是C mumbo-jumbo,它的写作和记录都非常好。在简单地说,这是它做什么:

  1. 调度员enters while循环,直到_finished财产变成true或者discovers递归。
  2. 里面的循环,它立即sets该属性到true,所以当它启动下一个迭代它会自动break
  3. 然后它获取控制器/动作信息,这些信息最初由应用程序中的路由器提供,并进行各种检查。在此之前和之后,它也完成了很多与事件相关的业务。
  4. 最后它calls控制器中的动作方法和updates_returnedValue属性用(猜猜是什么!)返回的值。
  5. 如果操作过程中打电话给你打电话Dispatcher::forward方法,它将update_finished财产回false,这将使该while循环从该名单中的第2步继续。

所以,你重定向或转发后,你需要确保你的代码没有得到执行只有如果是这样的预期逻辑的一部分。换句话说,您不必返回return $this->response->redirectreturn $this->dispatcher->forward的结果。

做最后一个看起来很方便,但不是很正确,可能会导致问题。在99.9%的情况下,你的控制器不应该返回任何东西。当你真的知道你在做什么并希望通过返回响应对象来呈现应用程序中的呈现过程的行为时,例外情况就是如此。最重要的是,您的IDE可能会抱怨不一致的返回语句。

要完成,正确的方法从控制器中重定向:

// Calling redirect only sets the 30X response status. You also should 
// disable the view to prevent the unnecessary rendering. 

$this->response->redirect('/profile'); 
$this->view->disable(); 

// If you are in the middle of something, you probably don't want 
// the rest of the code running. 

return; 

并转发:

$this->dispatcher->forward(['action' => 'profile']); 

// Again, exit if you don't need the rest of the logic. 

return; 
+0

''response-> redirect()'后不会有简单的'die()'吗? (我的意思是代替禁用视图并返回) – marcv

+2

在大多数情况下,是的,在某些情况下是否定的,例如,当某个逻辑运行在超出它的行为之后,并且包括Phalcon在内的大多数框架确实具有该逻辑时。在Phalcon案例中,从[这里](https://github.com/phalcon/cphalcon/blob/8aba8584d54237af9f2c0e5eba3dcc8a950cd225/ext/dispatcher.c#L964)上可以看到最后一个操作后会发生什么,尽管在大多数情况下,如果你死了,就不会扮演任何角色。 'die'是完成请求的一种拙劣的方式,对于为什么使用它是一种不好的做法,特别是在处理该请求的框架中使用它时,存在一些意见。 –

10

您需要使用这样的:

return $this->response->redirect('/profile'); 

return $this->dispatcher->forward(array(
    'action' => 'profile' 
)) 
+0

你如何从转发的控制器/操作获取内容而不使用回声? – vee

2

使用send()这样的

public function signinAction() 
{ 
    if ($this->isUserAuthenticated()) 
    { 
     return $this->response->redirect('profile')->send(); 
    } 
} 
+1

这帮助我解决了这个问题。我只使用了response-> redirect(预先使用view-> disable()),但我的操作(应该已经被登录保护)仍然被执行(即使显示了登录页面),添加了缺少的“ send()“让它工作。 – Select0r

+1

谢谢!我有分开的功能重定向,所以'返回'不起作用。你的解决方案帮了我 – Robin71