Можно ли использовать помощники действий не только для контроллеров? - PullRequest
1 голос
/ 27 марта 2012

Я ищу лучший способ использования сессии в приложении ZF. Сначала я сделал что-то вроде этого - в init методе суперкласса контроллера я инициализировал сессию:

class Vovkin_Controller_Action extends Zend_Controller_Action
{
    protected $_session;

    public function init()
    {   
        // here I define namespace 
        // ...
        $this->_session = new Zend_Session_Namespace($nameSpace);
        parent::init();
    }
    ...
}

после этого сеанса в контроллере использовался следующим образом:

public function someAction()
{
    $this->_session->user = $user;
}

но я обнаружил, что этот подход не очень удобен для других частей системы, таких как плагины, сервисы и т. Д., Потому что там я должен был инициировать сеанс другим способом, но я хочу сохранить его в одном месте, если это возможно. Поэтому я решил изменить его на этот подход https://stackoverflow.com/a/2506447.

Теперь у меня есть несколько помощников действий для предоставления доступа к сеансам с разными пространствами имен, это работает так:

public function someAction()
{
    $this->_helper->session()->user = $user;
}

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

class Vovkin_Model_Service_UserLoginService
{
    public function login()
    {
        $session = Zend_Controller_Action_HelperBroker::getStaticHelper('session')->direct();
        ...
    }   
    ....
}

но насколько правильно использовать его таким образом, с точки зрения архитектуры и используемых ресурсов?

Спасибо.

1 Ответ

2 голосов
/ 28 марта 2012

Ответ, на который вы сослались, принадлежит Робу Аллену, одному из основных разработчиков Zend Framework, так что в какой-то степени он прав. Вы можете без проблем работать с помощниками действий на контроллерах.

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

Таким образом, поскольку загрузчик приложения работает как контейнер для инициализации приложения, разумно получить от него необходимые значения. Первое, что я бы посоветовал вам использовать Zend_Registry. Но, насколько я могу судить, инициализация сеансового объекта будет такой же, поскольку он не будет удален, это просто объект, ссылающийся на собственные суперглобальные $_SESSION. Итак, просто позвоните

new Zend_Session_Namespace($nameSpace).

Но опять же, это неправильно. Вы не должны сообщать своим службам, как обрабатываются сеансы (таким образом создавая объекты внутри него):

$session = Zend_Controller_Action_HelperBroker::getStaticHelper('session')->direct()

или даже

$session = Zend_Registry('userSession')

или

$session = new Zend_Session_Namespace('userSession')

При этом вы также не используете контейнер начальной загрузки вообще. Вместо этого вы должны предоставить общий интерфейс для работы с сеансами (это может быть $ _SESSION или даже база данных) и добавить его в службу в качестве параметра (например, __construct($session)). Но это совершенно новый предмет (инъекция зависимости).

Итак, у вас есть два варианта, учитывая текущее состояние ZendFramework 1.11 (оно уже старое и полно плохих практик):

1) Вы будете пользоваться услугами через контроллеры:

Таким образом, вы получите сеанс через помощника действий, а затем передадите его в качестве параметра в службу.

new Vovkin_Model_Service_UserLoginService($session)

2) Вы будете использовать службы независимо от контроллеров и получите зависимости через контейнер начальной загрузки:

Что ж, хуже всего то, что для получения начальной загрузки вам нужна зависимость от frontController.

$bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap');

Итак, избегайте этого и перейдите к первому варианту, добавив вместо этого зависимость. Хотя, если вы действительно хотите таким образом, обращайтесь к нему напрямую:

$bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap');
$bootstrap->get('userSession')

К сожалению, в конце концов, все не так. Но это лучшее, что вы можете сделать с ZF 1. Вы должны рассчитывать на ZF 2 и Symfony 2, чтобы лучше понять эти концепции.

Вот хорошее объяснение: http://symfony.com/doc/current/book/service_container.html (Я знаю, что вы используете ZF, но это не имеет значения, концепция - это ключ)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...