Зачем использовать замыкание для присваивания вместо непосредственного присваивания значения ключу?

я смотрел это видео а в 7:10 он добавляет зависимость db и использует замыкание для присвоения значения.

Мой вопрос: почему бы просто не использовать прямое назначение, я имею в виду, не делает это:

$container['db'] = $capsule;

эквивалентно делать это:

$container['db'] = function ($container) use ($capsule) {
return $capsule;
}

Если нет, то какая разница и какой путь лучше?

6

Решение

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

Прыщ Контейнер для инъекций зависимостей, он должен помочь вам настроить ваши объекты, управляя их зависимостями простым и удобным способом.

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

$container['sample-param'] = 'foo';
echo $container['sample-param'];
//output: foo

Но дело в том, что это sample-param не требует никакой настройки, это просто значение, и мы в порядке с этим. Но допустим следующую настройку сервиса:

$container['myService'] = function($c) {
$service = new \Some\Complicated\Service();
//this service depends on cache service
$service->setCache($c['cache']);
return $service;
}

$container['cache'] = function($c) {
$cache = new \Cache\Driver();
//our cache driver needs a db connection
$cache->setDbConnection($c['db']);
return $cache;
}

$container['db'] = function($c) {
//our database connection requires some parameters
$dbConnection = new \Database\Connection($c['db-config']);
return $dbConnection;
}

$container['db-config'] = [
'username' => 'foo',
'password' => 'bar',
'host' => 'localhost'
];

//Now we want to user our service:
$container['myService']->doSomething();

Обратите внимание на порядок, который я использовал для определения разных ключей в контейнере.

myService потребности cache но определение кэша идет после определения myService. И здесь Pimple помогает, и именно поэтому мы передаем контейнер каждому закрытию, потому что Pimple собирается построить наши зависимости по требованию. Когда нам нужно получить доступ myService Pimple смотрит на свое внутреннее хранилище данных, если оно ранее построено и сохранено myService успешно, он вернет тот же экземпляр, иначе он вызовет наше закрытие, чтобы построить его. И когда наше закрытие вызывается, оно попросит Pimple ($ c — контейнер Pimple) дать ему dependecies (который в этом случае является cache оказание услуг). Pimple применяет то же самое к кешу, если он еще не создан, он будет его строить и так далее … пока не доберется до части, которая требует простых параметров, таких как db-config который немедленно вернется. И в этой цепочке вызовов замыканий наш объект и все его зависимости построены.

Теперь представьте, что произойдет, если мы используем простые значения вместо замыканий? В том случае, когда мы хотим построить myService мы должны заботиться о своих зависимостях. Мы должны убедиться, что его зависимости определены до мы определяем сам сервис и мы приходится иметь дело с другими проблемами, связанными с управлением зависимостями. В этом случае мы не могли бы просто определить наш myService а также предполагать Eсть cache услуга доступна, которая будет определена позже.

2

Другие решения

В этом видео он использует Slim Framework для контейнера, который по умолчанию использует Pimple для своего контейнера.

http://pimple.sensiolabs.org/

В документации на этой странице упоминается следующее

Определение сервисов Сервис — это объект, который делает что-то как часть
большей системы. Примеры услуг: подключение к базе данных,
шаблонизатор или почтовик. Почти любой глобальный объект может быть
оказание услуг.

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

// define some services
$container['session_storage'] = function ($container) {
return new SessionStorage('SESSION_ID');
};

$container['session'] = function ($container) {
return new Session($container['session_storage']);
};

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

По своей конструкции контейнеры ожидают вызова функции

Контейнеры прыща реализуют \ArrayAccess интерфейс (видно здесь), и это означает, что они могут заставить объект действовать как массив, не обязательно будучи единым целым. В исходном коде вы заметите offsetSet а также offsetGet, что происходит, когда вы делаете:

$container['a'] = function($c){ return new Blah();}

$thing = $container['a'];

ТЛ; др Это особенность контейнера Pimple, а не PHP.

0

Это абсолютно другое. Первый $container['db'] = $capsule;
значит что $container массив имеет db ключ и этот ключ равен $capsule,
второй означает, что у вас есть $container массив и db Ключ имеет значение закрытия. Вы можете увидеть разницу при выводе двух результатов:

Пример закрытия:

$capsule = 1;
$container['db'] = function ($container) use ($capsule) {
return $capsule;
};
var_dump($container);

Результат:

Array(1) {
["db"]=>
object(Closure)#1 (2) {
["static"]=>
array(1) {
["capsule"]=>
int(1)
}
["parameter"]=>
array(1) {
["$container"]=>
string(10) "<required>"}
}
}

Не закрывающийся пример:

$capsule = 1;
$container['db'] = $capsule;
var_dump($container);

Результат:

result array(1) {
["db"]=>
int(1)
}

Вы можете прочитать о замыканиях в руководстве по PHP для лучшего понимания их роли. Руководство по закрытию PHP

-1
По вопросам рекламы ammmcru@yandex.ru