Подтвердить что ты не робот

Как я могу использовать "Injection Dependency" в простых функциях php, и должен ли я беспокоиться?

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

Мне интересно, если это решение проблемы "Я передаю соединения базы данных как аргументы все время".

Я пробовал читать на нем запись в wikipedia, но пример написан на Java, поэтому я не понимаю, в чем разница, которую он пытается прояснить. (http://en.wikipedia.org/wiki/Dependency_injection).

Я прочитал эту статью с зависимостями-инъекциями в PHP (http://www.potstuck.com/2009/01/08/php-dependency-injection/), и кажется, что цель состоит в том, чтобы не передавать зависимости к объекту напрямую, но чтобы оцеплять создание объекта вместе с созданием его зависимостей. Я не уверен, как применять это в контексте использования php-функций.

Кроме того, это следующая инъекция зависимостей, и я должен попытаться сделать инъекцию зависимостей в функциональном контексте?

Версия 1: (тип кода, который я создаю, но не люблю, каждый день)

function get_data_from_database($database_connection){
    $data = $database_connection->query('blah');
    return $data;
}

Версия 2: (не нужно пропускать соединение с базой данных, но, возможно, не впрыскивание зависимостей?)

function get_database_connection(){
    static $db_connection;
    if($db_connection){
        return $db_connection;
    } else {
        // create db_connection
      ...
    }
}

function get_data_from_database(){
   $conn = get_database_connection();
   $data = $conn->query('blah');
   return $data;
}

$data = get_data_from_database();

Версия 3: (создание "объекта" /данных является отдельным, а код базы данных по-прежнему, поэтому, возможно, это будет считаться инъекцией зависимостей?)

function factory_of_data_set(){
    static $db_connection;
    $data_set = null;
    $db_connection = get_database_connection();
    $data_set = $db_connection->query('blah');
    return $data_set;
}

$data = factory_of_data_set();

У кого-то есть хороший ресурс или просто проницательность, которая делает метод и преимущества -кристаллическими?

4b9b3361

Ответ 1

Вложение зависимостей - большое слово для "У меня есть еще несколько параметров в моем конструкторе".

Это то, что вы делали до awfull Singleton, когда вам не нравились глобальные переменные:

<?php
class User {
    private $_db;
    function __construct($db) {
        $this->_db = $db;
    }
}

$db   = new Db();
$user = new User($db);

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

class DependencyContainer 
{
    private _instances = array();
    private _params = array();

    public function __construct($params)
    {
        $this->_params = $params;
    }

    public function getDb()
    {
        if (empty($this->_instances['db']) 
            || !is_a($this->_instances['db'], 'PDO')
        ) {
            $this->_instances['db'] = new PDO(
                $this->_params['dsn'],
                $this->_params['dbUser'], 
                $this->_params['dbPwd']
            );
        }
        return $this->_instances['db'];
    }
}

class User
{
    private $_db;
    public function __construct(DependencyContainer $di)
    {
         $this->_db = $di->getDb();
    }
}

$dependencies = new DependencyContainer($someParams);
$user = new User($dependencies);

Вы должны думать, что вы просто еще один класс и сложнее. Но вашему пользовательскому классу может понадобиться что-то, чтобы регистрировать сообщения, такие как много других классов. Просто добавьте функцию getMessageHandler в контейнер зависимостей, а некоторые $this->_messages = $di->getMessageHandler() - к вашему классу пользователей. Ничего не изменится в остальной части вашего кода.

Вы получите много информации о symfony doc

Ответ 2

В первом примере IS зависимой инъекции вы вводите зависимость от объекта базы данных в функцию.

Сара сказала, что это не так, но я думаю, что она думает о контейнерах для инъекций зависимостей, которые находятся на следующем уровне:

http://components.symfony-project.org/dependency-injection/trunk/book/02-Dependency-Injection-Containers

Ответ 3

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

Чтобы обойти проблему "всегда передавать объект соединения", вы можете рассмотреть шаблон шаблона. Шаблон шаблона в основном представляет собой абстрактный базовый класс с общей частью повторяющегося блока кода и абстрактные методы, позволяющие варьировать между экземплярами этих повторяющихся кодовых блоков. В основном база является шаблоном блока кода, а абстрактные методы - это заполняемые пробелы. Я лично использую шаблон шаблона метода для управления ресурсами базы данных в Java.

Ответ 4

Я сделал большой поиск по этой теме самостоятельно (PHP Dependency Injection) и не нашел много по своему вкусу. Многое было написано на эту тему для других языков (Google Guice - http://code.google.com/p/google-guice/, Java Spring), но я не мог найти доступно для PHP. Однако, независимо от языка, проблемы схожи.

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

Пример контейнера зависимостей от @Arkh и @mmmshuddup - отличный старт, но я тем не менее нашел ограничения и с этим подходом. Окончательное решение, по которому я приехал, было специально построенным решением, смоделированным несколько после того, как популярный шаблон Cake в Scala. Он позволяет передавать одну зависимость в каждый из ваших конструкторов. И она позволяет определять конструкцию по умолчанию для зависимых объектов для каждого класса. Это освобождает вас от длинных цепочек зависимостей, а также утрачивает контроль над реалиями ваших зависимостей по умолчанию.

Я назвал систему Diesel, и я был очень доволен ею. Я опубликовал код для github для всех, кого это интересует. Вы можете перейти к нему из блога, который я написал по этому вопросу, в котором описывается основное использование, а также более подробно изложено в вашем вопросе. http://developers.blog.box.com/2012/02/15/introducting-diesel-php-dependency-injection/

Ответ 5

Инъекция зависимостей - это идея удаления зависимости между двумя компонентами, чтобы сосредоточиться на том, почему они зависят.

Представьте, что у вас есть компонент A, которому необходимо использовать службы другого компонента B.

Если вы жестко указали существование B внутри A, тогда вы будете застревать, когда вы захотите, чтобы A использовал службы sames, но реализован другим компонентом.

Как правило, вы определяете интерфейс службы, который реализует B и C, и убедитесь, что при использовании A вы передаете его объектам, совместимым с необходимым интерфейсом.

В вашем случае вы можете подумать, что ваш интерфейс является сервисом, по которому вы можете сделать запрос.

Ваш первый случай - это тот, который ближе к идее Injection Dependency.