2

通常、これは私が質問するような質問ではありません。私が見逃しているのはばかげたものだと思うからです。

(疑わしい) エラーが発生するセットアップを説明するには: 基本的な CRUD コントローラー (または私の場合は推奨の NERD) を使用して、4 つのアクションを実行します。

  • 新着
  • 編集
  • 読んだ
  • 消去

読み取り、編集、および削除アクションには、ブログ投稿などのオブジェクトが必要であり/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;
    }
}

問題

このコードは完全に機能しますが、2 つの条件が発火したとしても、何らかの理由で がトリガーされず、アプリケーションがビューをレンダリングし、その後の non-object への無効なアクセスでエラーが発生する場合を除きreadAction()ます。validatePostId()return $this->redirect()$post

私は何千回もチェックしましたが、有効かどうかをチェックする条件$postが実際に入力されているので、リダイレクトが呼び出されると確信しています。私が見つけたが説明できないヒントは次のとおりです。read アクションを次のように変更すると、1 行追加するだけです。

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

1 に答える 1

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;
    }
}
于 2013-10-27T08:20:26.980 に答える