CakePHP 2.0 - beforeFilter () не запускается на cakeErrorController?

Я работал с CakePHP 1.3, но это мое первое знакомство с исключениями CakePHP 2.0 и PHP, так что потерпите, если мой вопрос покажется многословным.

В моем AppController beforeFilter() я установил пару переменных через $this->set() для использования в моем шаблоне представления.

В моем UsersController у меня есть код, который выглядит примерно так:

public function beforeFilter() {
  parent::beforeFilter();
  if (userDeniedAccess()) {
    throw new ForbiddenException();
  }
}

где гипотетическая функция userDeniedAccess() инкапсулирует мои проверки авторизации.

Все это работает нормально, и я получаю ошибку 403, когда ожидаю этого. Однако при возникновении исключения переменные представления, которые были установлены в AppController::beforeFilter(), больше не устанавливаются, что приводит к ошибкам из моего шаблона представления. Когда исключение не выдается, переменные установлены правильно.

Я могу кодировать отсутствующие переменные, если нужно, но мне бы очень хотелось знать, что вызывает такое поведение. И мой UsersController, и CakeErrorController расширяют AppController. Естественно, я ожидаю, что при возникновении исключения и создании экземпляра CakeErrorController для меня будут генерироваться одни и те же переменные представления.

Однако похоже, что метод Controller::startupProcess() (который включает вызов beforeFilter()) никогда не вызывается для CakeErrorController. Я так понимаю, это делает диспетчер для обычных запросов, но жизненный цикл контроллера ошибок другой.

Я видел описания (подобные этому) аналогичного поведения в CakePHP 1.3, но, конечно же, код обработки ошибок CakePHP был полностью переработан в версии 2.0.

Так что либо:

  1. Это ошибка в обработке исключений CakePHP по умолчанию.
  2. Поведение соответствует задуманному, и я просто не понимаю его, или
  3. Я схожу с ума.

Я знаю, что вы не можете помочь со случаем 3, но если подойдет любой из первых двух, я был бы признателен за помощь того, кто знает больше меня.

Спасибо!

EDIT: Установка переменных представления в beforeRender() действительно решает мою проблему. Тем не менее, мне все еще интересно, намеренно ли beforeFilter() никогда не вызывается CakeErrorController.


person eaj    schedule 27.01.2012    source источник
comment
+1, потому что я могу быть сумасшедшим самодиагностом.   -  person Justin ᚅᚔᚈᚄᚒᚔ    schedule 28.01.2012


Ответы (2)


Поместите вызовы $this->set() в обратный вызов beforeRender(). Таким образом, они всегда будут установлены, даже если вы создадите исключение.

У меня была такая же проблема с некоторыми пользовательскими переменными макета, так как с DebugKit моя страница заполнялась предупреждениями о необъявленных переменных всякий раз, когда возникала какая-либо ошибка. Использование beforeRender() вместо этого исправило это.

person mrlee    schedule 27.01.2012
comment
+1 за содержательный ответ, но я не уверен, что это сработает для меня, так как beforeRender() запускается после логики действия. Поскольку я выполняю проверки авторизации, я не хочу, чтобы логика действий запускалась в случае сбоя. - person eaj; 28.01.2012
comment
Если подумать, это не имеет смысла. Конечно, я могу бросить свое исключение в beforeFilter() и установить переменные представления в beforeRender(). Я принял этот ответ, так как он решает мою насущную проблему, но мне все же хотелось бы знать, является ли ошибкой то, что beforeFilter() не вызывается в контроллере ошибок. - person eaj; 01.02.2012

вы можете перезаписать CakeErrorController.php, скопировав его в App/Controller/, а затем добавить parent::beforeFilter() в конструктор.

person csx    schedule 09.02.2012
comment
Спасибо, это, безусловно, полезная опция. Однако это кажется немного хакерским. На данный момент мой код делает то, что ему нужно. Я все еще хотел бы понять, почему процесс обработки исключений никогда не вызывает startupProcess() на CakeErrorController так же, как диспетчер вызывает его на других контроллерах. - person eaj; 09.02.2012