php - Zend框架2 : redirect toRoute shortcircuit not triggering

标签 php redirect zend-framework2

通常这不是我会问的问题,因为我预计这是我错过的一些愚蠢的事情,但在调试过程中我发现了一些非常奇怪的行为,这确实让我感到困惑。

描述发生(疑似)错误的设置:我有一个基本的 CRUD Controller (或者在我的情况下是首选 NERD),其中我有四个操作:

  • 编辑
  • 阅读
  • 删除

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

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

我在同一 Controller 中的单独公共(public)函数中进行检查,以防止代码重复。

代码:

<?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()中的两个条件触发,返回$this->redirect() 不知何故未触发,应用程序渲染 View 并因无效访问非对象 $post 而导致后续错误。

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

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

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

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

问题消失了,应用程序巧妙地重定向。然而,这没有意义。该行只是调用 Controller 中实例化表单的公共(public)函数,据我所知,这应该没有效果。情况会变得更糟,如果我从该行删除 ->bind() 调用,老问题又回来了。所以我所能弄清楚的是,操作的差异似乎是在调用 validatePostId() 和返回 View 之间没有任何额外的代码,这实际上不应该事...

编辑:

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

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
    );
}

最佳答案

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

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

<?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;
    }
}

关于php - Zend框架2 : redirect toRoute shortcircuit not triggering,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19614250/

相关文章:

PHP APNS 一个 token 失败

c++ - 动态分配的控制台 I/O 的 Visual Studio 2015 问题

mysql - 从 Zend Framework 2 中生成的 MYSQL 中删除引号

php - 页面完全加载后如何加载 PHP 页面?

php - preg_match_all 到简单数组

php - Javascript 数组中的当前条目

http - IIS HTTP 到 HTTPS 相对重定向

cakephp - nginx 正在从一个虚拟主机重定向到另一个

php - 在 Zend Framework 2 (ZF2) 中创建新 Controller 的问题

validation - 在 Zend 框架 2 中验证日期