Содержание


Быстрый старт


ZendDi Quickstart, ЗФ2, Zend Framework 2, ZF2, ру, ru




Раздел быстрый старт предназначен для разработчиков, уже хоть немного знакомых с Zend\Di DiC или подобным. Столь простой код, как будет рассмотрен,  употребляется очень редко. Поэтому желательно наличие знаний из других основных разделов документации или понимание принципов работы в аналогии на других языках  программирования.

 

Предположим, что следующий пример кода – это часть Вашего приложения. Он хорошо подходит для использования DiC. А также все необходимые зависимости уже инъецированы.

namespace MyLibrary
{
    class DbAdapter
    {
        protected $username = null;
        protected $password = null;
        public function __construct($username, $password)
        {
            $this->username = $username;
            $this->password = $password;
        }
    }
}
 
namespace MyMovieApp
{
    class MovieFinder
    {
        protected $dbAdapter = null;
        public function __construct(\MyLibrary\DbAdapter $dbAdapter)
        {
            $this->dbAdapter = $dbAdapter;
        }
    }
 
    class MovieLister
    {
        protected $movieFinder = null;
        public function __construct(MovieFinder $movieFinder)
        {
            $this->movieFinder = $movieFinder;
        }
    }
}

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

// $config object is assumed
 
$dbAdapter = new MyLibrary\DbAdapter($config->username, $config->password);
$movieFinder = new MyMovieApp\MovieFinder($dbAdapter);
$movieLister = new MyMovieApp\MovieLister($movieFinder);
foreach ($movieLister as $movie) {
    // iterate and display $movie
}

Если вы сделаете это в контроллере или шаблоне вида, то получите список фильмов. Однако это довольно скучно писать везде, где нужно вывести список фильмов, а так же изменение любой из зависимостей сопряжено с определенными трудностями.

 

Только что мы ознакомились с хорошим классическим применением инъекции зависимостей через конструктор. Теперь рассмотри как сделать тоже самое через Zend\Di:

// inside a bootstrap somewhere
    $di = new Zend\Di\Di();
    $di->instanceManager()->setParameters('MyLibrary\DbAdapter', array(
        'username' => $config->username,
        'password' => $config->password
    ));
 
    // inside each controller
    $movieLister = $di->get('MyMovieApp\MovieLister');
    foreach ($movieLister as $movie) {
        // iterate and display $movie
    }

Сначала создали дефолтный экземпляр Zend\Di\Di. Под дефолтным нужно понимать: Zend\Di\Di создан с помощью DefinitionList используя RuntimeDefinition ( через Reflection) и пустоу экземпляр менеджера без конфигураций.

 

Рассмотрим конструктор Zend\Di\Di:

 public function __construct(DefinitionList $definitions = null, InstanceManager $instanceManager = null, Configuration $config = null)
    {
        $this->definitions = ($definitions) ?: new DefinitionList(new Definition\RuntimeDefinition());
        $this->instanceManager = ($instanceManager) ?: new InstanceManager();
 
        if ($config) {
            $this->configure($config);
        }
    }

Тоесть, при вызове «$di->get()», будет произведено обращение к RuntimeDefinition, который использует отражение (reflection) для понимания структуры кода. Как только структура кода будет изучена, станет известны взаимосвязи зависимостей и как и куда их инъекцировать. Zend\Di\Definition\RuntimeDefinitionиспользует имена параметров в методах как имена параметров класса (names of the parameters in the methods as the class parameternames – если знаете лучший перевод, пожалуйста, сообщите). Таким образом ключи «username» и «password»  передаются как первый и второй параметры в соответствующий конструктор.

 

Если же Вам необходимо передавать «username» и «password» непосредственно во время вызова, то необходимо передать их как второй параметр в метод «get()»:

   // inside each controller
    $di = new Zend\Di\Di();
    $movieLister = $di->get('MyMovieAppMovieLister', array(
        'username' => $config->username,
        'password' => $config->password
    ));
    foreach ($movieLister as $movie) {
        // iterate and display $movie
    }

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

 

После вызова «$di->get()», экземпляр MovieLister становится общедоступным автоматически. Тоесть последующие вызовы «get()» буду возвращать те же результаты, что и предыдущие. Если же Вам необходим совершенно новый экземпляр MovieLister воспользуйтесь метод «$di->newInstance()».


Автор статьи: DuB