Phalcon重定向和转发

14
我理解得对吗,执行$this->dispatcher->forward()$this->response->redirect()后,我需要手动确保不会继续执行其余的代码吗?就像下面这样,还是我漏掉了什么?
public function signinAction()
{
    if ($this->isUserAuthenticated())
    {
        $this->response->redirect('/profile');
        return;
    }

    // Stuff if he isn't authenticated…
}
3个回答

28

经过近一年的开发,我在一个超出Phalcon容量的项目上工作,想澄清一些事情并回答自己的问题。要了解如何正确地进行重定向和转发,您需要了解Dispatcher::dispatch方法的一些知识。

看看这里的代码here,尽管对我们大多数人来说都是C语言胡言乱语,但它确实写得非常好并且有文档记录。简而言之,它所做的就是:

  1. 调度程序 进入 while 循环,直到 _finished 属性变为 true 或者它 发现 递归。
  2. 在循环内部,它立即 设置 该属性为 true,因此当它开始下一次迭代时,它将自动 中断
  3. 然后获取控制器/操作信息,这些信息最初由应用程序中的路由器提供,并进行各种检查。在此之前和之后,还会完成许多与事件相关的业务。
  4. 最后,它 调用 控制器中的操作方法,并使用(猜猜看!)返回的值 更新 _returnedValue 属性。
  5. 如果在操作调用期间调用 Dispatcher::forward 方法,则会将 _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;

response->redirect() 之后,一个简单的 die() 不就足够了吗?(我的意思是禁用视图并返回的代替方案) - marcv
2
在大多数情况下是的,在某些情况下不是,例如当有一些逻辑要在操作之后运行时,而且大多数框架(包括Phalcon)都有这种逻辑。在Phalcon的情况下,从这里可以看到最后一个操作之后发生了什么,尽管在大多数情况下,如果您在其中使用die,那么它并不起任何作用。die是完成请求的hacky方式,对于为什么在处理该请求的框架中使用它是不良实践的,有一些意见。 - Ian Bytchek

10

你需要这样使用它:

return $this->response->redirect('/profile');
或者
return $this->dispatcher->forward(array(
    'action' => 'profile'
))

1
不使用echo,如何从转发的控制器/动作获取内容? - vee

2

使用send()的方法如下:

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

1
这帮助我解决了问题。我之前只使用了response->redirect(在view->disable()之前),但是我的操作(本应该由登录保护)仍然被执行(即使显示了登录页面),添加缺失的“send()”后它开始工作了。 - Select0r
1
谢谢!我已经分离了重定向函数,所以 return 不起作用。你的解决方案帮了我很大的忙。 - Robin71

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接