Zend框架2:重定向到路由短路不触发

时间:2013-10-27 03:17:28

标签: php redirect zend-framework2

通常情况下,这不是我要问的那种问题,因为我希望这是一个让我感到愚蠢的事情,但是在调试中我发现了一些非常奇怪的行为让我感到难过。

描述发生(可疑)错误的设置:我有一个基本的CRUD控制器(或者在我的情况下是首选的NERD),我有四个动作:

  • new
  • 修改
  • 删除

读取,编辑和删除操作需要一个对象,比如一个博客帖子,并且需要提供由/post/read/[:id]这样的路由调用的URL。我在每个动作中做的第一件事是检查(a)是否设置了id参数,以及(b)id对应于存储在数据库中的有效实体(我使用Doctrine 2作为映射器)。如果(a)或(b)失败,我立即返回并重定向到索引操作:

 return $this->redirect()->toRoute('post/index');

我在同一控制器中的单独公共函数中进行检查,以防止代码重复。

代码:

<?php

namespace Blog\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\Mvc\Controller\Plugin\FlashMessenger as FlashMessenger;

class PostController extends AbstractActionController
{

    public function editAction()
    {
        $post_id = $this->params()->fromRoute('id');
        $post    = $this->validatePostId($post_id);

        // Create/Validate forms and persist/flush

        return array(
            'post' => $post,
            'form' => $form
        );
    }

    public function deleteAction()
    {
        $post_id = $this->params()->fromRoute('id');
        $post    = $this->validatePostId($post_id);

        // Remove post from database
        $this->getBlogService()->deletePost($post);
        $this->flashMessenger()->addSuccessMessage('Post successfully deleted');
        return $this->redirect()->toRoute('post');
    }

    public function readAction()
    {
        $post_id = $this->params()->fromRoute('id');
        $post    = $this->validatePostId($post_id);

        return array(
            'post' => $post
        );
    }

    /**
     * Checks if $id from url is set and tries to find the corresponding post
     */
    public function validatePostId($post_id)
    {        
        if (!$post_id) {
            $this->flashMessenger()->addErrorMessage('Invalid post id');
            return $this->redirect()->toRoute('post');
        }

        $post = $this->getBlogService()->getPostById($post_id);

        if ($post == NULL) {
            $this->flashMessenger()->addErrorMessage('Invalid post id');
            return $this->redirect()->toRoute('post');
        }

        return $post;
    }
}

问题

此代码完美地运行除了readAction() ,即使validatePostId()中的两个条件触发,return $this->redirect()也会以某种方式触发,应用程序呈现无效访问非对象$post时查看和后续错误。

我已经检查了一千次,并且确实输入了检查有效$post的条件,因此我确信调用了重定向。我发现但无法解释的提示如下。如果我将读取操作更改为以下内容,只需添加一行:

public function readAction()
{
    $post_id = $this->params()->fromRoute('id');
    $post    = $this->validatePostId($post_id);

    $form    = $this->getPostForm()->bind();

    return array(
        'post' => $post
    );
}

问题消失,应用程序整齐重定向。然而,这没有意义。该行只调用控制器中的一个公共函数来实例化一个表单,据我所知,这应该没有效果。情况变得更糟,如果我从该行删除了->bind()来电,旧的问题又回来了。所以我能够弄清楚的是,操作的差异似乎是在调用validatePostId()和返回视图之间没有任何额外的代码,这应该不重要...... < / p>

编辑:

更新,如果我直接使用validatePostId()readAction()函数的代码,问题也会消失:

public function readAction()
{
    $post_id = $this->params()->fromRoute('id');
    $post    = $this->validatePostId($post_id);

    if (!$post_id) {
        $this->flashMessenger()->addErrorMessage('Invalid post id');
        return $this->redirect()->toRoute('post');
    }

    $post = $this->getBlogService()->getPostById($post_id);

    if ($post == NULL) {
        $this->flashMessenger()->addErrorMessage('Invalid post id');
        return $this->redirect()->toRoute('post');
    }

    return array(
        'post' => $post
    );
}

1 个答案:

答案 0 :(得分:3)

在控制器中调用$this->redirect()的行为不会自动重定向到新位置,它只会返回一个Response对象,然后您需要从控制器操作返回该对象以便短路请求。

由于您从另一个函数返回redirect()调用的结果,因此您需要首先测试该调用的结果是否为Response对象并在控制器操作中处理它...

<?php

namespace Blog\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\Mvc\Controller\Plugin\FlashMessenger as FlashMessenger;

use Zend\Stdlib\ResponseInterface as Response;

class PostController extends AbstractActionController
{

    public function readAction()
    {
        $post_id = $this->params()->fromRoute('id');
        $post    = $this->validatePostId($post_id);

        // check to see if post validation returned a Response 
        if ($post instanceof Response) {
            // redirect...
            return $post;
        }

        return array(
            'post' => $post
        );
    }

    /**
     * Checks if $id from url is set and tries to find the corresponding post
     */
    public function validatePostId($post_id)
    {        
        if (!$post_id) {
            $this->flashMessenger()->addErrorMessage('Invalid post id');
            return $this->redirect()->toRoute('post');
        }

        $post = $this->getBlogService()->getPostById($post_id);

        if ($post == NULL) {
            $this->flashMessenger()->addErrorMessage('Invalid post id');
            return $this->redirect()->toRoute('post');
        }

        return $post;
    }
}