Обычно это не тот вопрос, который я задал бы, так как я ожидаю, что это что-то глупое, чего мне не хватает, но в отладке я нашел какое-то действительно странное поведение, которое действительно меня насторожило.Zend framework 2: redirect toRoute shortcircuit не запускается
Чтобы описать установку, в которой происходит (предположительно) ошибка: У меня есть основной CRUD-контроллер (или предпочтительный NERD в моем случае), где у меня есть четыре действия:
- новый
- редактировать
- чтения
- удалить
Считанные, редактировать и удалять действия требуют объект, скажем BlogPost, и URL вызывается такой маршрут, как /post/read/[:id]
, должен быть предоставлен идентификатор. Первое, что я делаю в каждом из этих действий, - проверить, что (a) установлен параметр id, и что (b) идентификатор соответствует действительному объекту, хранящемуся в базе данных (я использую Doctrine 2 в качестве mapper). Если какой-либо (а) или (б) не удается, я немедленно вернуться и перенаправить к действию индекса:
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()
и возвратом вида, что не имеет особого значения ...
Редактировать :
обновление, если я непосредственно использовать код функции 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
);
}
Интересно, что для проверки empty() вместо == NULL. – Ryan
'empty()' не имеет значения – Pankrates
последнее исправление говорит о том, что что-то идет не так в $ post = $ this-> getBlogService() -> getPostById ($ post_id); В исходном коде, если вы var_dump ($ post_id) и var_dump ($ post) перед возвратом, и оба они все равно null, я в тупике. Возможно, что-то пойдет не так после redirect -i.e. везде, где идет маршрут («сообщение»). +1 для вашего аватара, btw – Ryan