通常这不是我会问的那种问题,因为我认为我错过了一些愚蠢的东西,但是在调试中我发现了一些非常奇怪的行为,这真的让我很难过。
描述发生(疑似)错误的设置:我有一个基本的 CRUD 控制器(或在我的情况下首选的 NERD),其中我有四个操作:
- 新的
- 编辑
- 读
- 删除
读取、编辑和删除操作需要一个对象,例如一篇博文,并且/post/read/[:id]需要提供由 id 之类的路由调用的 url。我在每个操作中做的第一件事是检查 (a) id 参数是否已设置以及 (b) id 是否对应于存储在数据库中的有效实体(我使用 Doctrine 2 作为映射器)。如果 (a) 或 (b) 失败,我会立即返回并重定向到 index 操作:
 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()也不会以某种方式触发,并且应用程序呈现视图和随后的错误以及对 non-object 的无效访问$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()和返回视图之间没有任何额外的代码,这并不重要......
编辑:
更新,如果我直接使用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
    );
}