Как запустить одинаковые строки во всех функциях init() контроллеров?

Мне нужны одинаковые 2 строки во всех моих контроллерах, у каждого контроллера своя логика инициализации, но эти две строки общие для всех.

public function init()
{
    $fm =$this->_helper->getHelper('FlashMessenger');
    $this->view->messages = $fm->getMessages();
}

Как избежать повторения кода?

Обновление:

Хорошо, FlashMessenger был только примером, скажем, мне нужно написать строку журнала для каждого действия, кроме 'someAction' @ 'someController'. Такими должны быть новые общие линии.

$this->logger = new Zend_Log();
$writer = new Zend_Log_Writer_Stream(APPLICATION_PATH.'/../logs/log.txt');
$this->logger->addWriter($writer);
$this->logger->log('Some Message',Zend_Log::DEBUG);

Вопрос в том, где мне разместить эти строки, чтобы они не повторялись во всех init() каждого контроллера. Эти строки должны быть размещены в bootstrap?. Если да: как можно пропустить строки журнала для «someAction». Или я должен реализовать «BaseController» и сделать так, чтобы весь мой контроллер расширялся от него. Если да: как я могу автоматически загрузить его? (Неустранимая ошибка: класс BaseController не найден).


person texai    schedule 18.02.2011    source источник


Ответы (5)


Просто подкласс контроллера:

class Application_ControllerAction extends Zend_Controller_Action {
    public function init()
    {
        $fm =$this->_helper->getHelper('FlashMessenger');
        $this->view->messages = $fm->getMessages();
    }
}


class IndexController extends Application_ControllerAction {
}

Вы также можете добиться того же написания плагина контроллера.

Редактировать:

Плагины переднего контроллера выполняются при каждом запросе, как и Controllers, и имеют те же методы перехвата:

routeStartup(): prior to routing the request
routeShutdown(): after routing the request
dispatchLoopStartup(): prior to entering the dispatch loop
preDispatch(): prior to dispatching an individual action
postDispatch(): after dispatching an individual action
dispatchLoopShutdown(): after completing the dispatch loop

Кроме того, вы можете проверить параметры контроллера, чтобы код выполнялся только для выбранных запросов:

if ('admin' == $this->getRequest()->getModuleName() 
&& 'update' == $this->getRequest()->getActionName() ) …
person takeshin    schedule 19.02.2011
comment
Пожалуйста, объясните, как поможет плагин контроллера - person texai; 19.02.2011
comment
Я рекомендую использовать хелпер представления вместо подкласса контроллера, так как хелперы представления созданы именно для этой цели. Подкласс класса Controller является обычным подходом в других фреймворках, но Zend предоставляет вспомогательную функциональность. Кстати, то же самое касается помощников действий. - person Martijn; 20.02.2011

Вы можете получить доступ к своим флэш-сообщениям через (вам не нужно ничего отправлять с вашего контроллера на ваше представление, все это автоматизировано)

$fm = new Zend_Controller_Action_Helper_FlashMessenger();
Zend_Debug::dump($fm->getMessages());

в вашем представлении я бы также рекомендовал вам инкапсулировать этот код в помощнике представления, как показано на этом сайте http://grummfy.be/blog/191

person JF Dion    schedule 18.02.2011
comment
@Jeff: Спасибо за ваш ответ, но я все еще хочу знать, как избежать повторения кода во всех ваших контроллерах. - person texai; 18.02.2011
comment
Я задал похожий вопрос относительно этого stackoverflow.com/questions/4347965/ - person JF Dion; 18.02.2011
comment
@Jeff: Кроме того, я предпочитаю не писать new в своих представлениях. - person texai; 18.02.2011
comment
@texai: я могу понять ваши предпочтения в кодировании, и меня это устраивает, но если вы обратитесь к теоретическому шаблону проектирования MVC, контроллеры и представления могут вызывать модели, поэтому, помимо предпочтений в кодировании, в этом нет ничего плохого (en.wikipedia.org/wiki/Model_view_controller) - person JF Dion; 18.02.2011
comment
@Jeff: Иногда я вызываю статические методы своих классов моделей из представлений, но я предпочитаю делать new в контроллерах. - person texai; 19.02.2011
comment
@Jeff FlashMessenger был лишь примером. Я установил новый пример, пожалуйста, смотрите обновление. - person texai; 19.02.2011

В вашем бутстрапе:

protected function _initMyActionHelpers() {
    $fm = new My_Controller_Action_Helper_FlashMessenger();
    Zend_Controller_Action_HelperBroker::addHelper($fm);;
}
person Stephen Fuhry    schedule 18.02.2011
comment
FlashMessenger был только примером. Пожалуйста, смотрите обновление вопроса. - person texai; 19.02.2011

Как избежать повторения кода?

Напишите свой собственный пользовательский контроллер, реализуйте его в методе init этого контроллера, а затем расширьте все контроллеры в своем приложении из своего пользовательского контроллера.

Но подход с отдельным помощником представления, как упоминал @Jeff (см. ссылку), часто воспринимается как лучшее решение. В вашем контроллере выполните только:

$this->_helper->flashMessanger('My message');

и помощник просмотра сделает все остальное.

person Radek Benkel    schedule 18.02.2011
comment
Это поражение всего смысла действия помощников! из документации: Помощники действий стремятся свести к минимуму необходимость расширения абстрактного контроллера действий, чтобы внедрить общие функции контроллера действий framework.zend.com/manual/en/zend.controller.actionhelpers.html - person Stephen Fuhry; 19.02.2011
comment
Я не говорил, что это хорошее решение. Подробнее - я написал, что view helper будет лучше и предложил код без использования init! Но вопрос был: как запустить что-то во всех контроллерах с функцией init - и то, что я написал, является чистым ответом на этот вопрос. Поэтому я думаю, что минусовать меня несправедливо. - person Radek Benkel; 19.02.2011

Это не причина для создания нового пользовательского контроллера. Просто добавьте эту строку ко всем методам init().

$this->view->messages = $this->_helper->getHelper('FlashMessenger')->getMessages();
person KomarSerjio    schedule 18.02.2011
comment
Это как раз то, чего я хочу избежать - person texai; 19.02.2011