#php #dependency-injection #doctrine-orm
#php #внедрение зависимостей #doctrine-orm
Вопрос:
Я разрабатываю php-приложение с Doctrine (без symfony) и, следовательно, без контейнера DI. Я использую внедрение зависимостей в одной из моих сущностей, которой нужен сервис.
Class A implements Ia
{
public function __constructor( requiredServiceClass $requiredService = NULL )
{
if ($requiredService === NULL) {
$this->requiredService = new requiredServiceClass();
{
$this->requiredService = $requiredService;
}
}
}
Все работает нормально, но при гидратации Doctrine не вызывает __constructor, в результате зависимость не вводится.
Каков наилучший способ решить эту проблему?
В настоящее время я использую события жизненного цикла Doctrine для обратного вызова метода для установки зависимости. Итак, сначала я добавляю обратные вызовы жизненного цикла в файл сопоставления объекта
<lifecycle-callbacks>
<lifecycle-callback type="postLoad" method="setRequiredService"/>
</lifecycle-callbacks>
И затем в вызываемом методе вводите зависимость, применяя внедрение установщика зависимостей.
public function setRequiredService()
{
$this->requiredService = new requiredServiceClass();
}
Мои вопросы:
Это лучший способ решить проблему внедрения зависимостей во время гидратации в Doctrine?
И нормально ли передавать параметр DI с значением по умолчанию NULL?
Спасибо, Абхинит Рави
Ответ №1:
Хранит ли он какую-либо информацию в базе данных для этого «Сервиса», я не уверен, что это такое.
Если это так, вы могли бы определить его как пользовательский тип данных. Вот ссылка на doctrine docs по этой теме.
http://doctrine-orm.readthedocs.org/en/latest/cookbook/custom-mapping-types.html
http://docs.doctrine-project.org/en/2.0.x/cookbook/mysql-enums.html
Я не вижу никаких проблем, если это просто какой-то класс, который вам нужен, не уверен, не зная, что такое service, и было бы лучше реструктурировать код, чтобы он не нуждался в этом, но я не могу сказать, не зная, что это делает.
Я бы сказал, что способ, которым вы это делаете, в порядке, не уверен, запускается ли onLoad только при извлечении из базы данных или нет, но вы можете захотеть проверить, есть ли там null вместо этого.
Я бы, возможно, написал класс таким образом
Class A implements Ia
{
protected $requiredService; //null by default
public function __constructor( requiredServiceClass $requiredService = NULL )
{
$this->setRequiredService($requiredService);
}
public function postLoad(){
$this->setRequiredService();
}
public function setRequiredService(requiredServiceClass $requiredService = NULL)
{
if(NULL === $this->requiredService){
//check if class has service - assuming you never want to set it again once it is set.
if(NULL === $requiredService){
$this->requiredService = new requiredServiceClass();
}else{
$this->requiredService = $requiredService;
}
}
}
}
<lifecycle-callbacks>
<lifecycle-callback type="postLoad" method="postLoad"/>
</lifecycle-callbacks>
Мои причины таковы.
- Таким образом, все ваши проверки выполняются прямо перед внедрением сервиса в класс.
- Из кода ясно, что используется обратный вызов жизненного цикла.
- Лучше следует за разделением проблем, т. Е. конструктор не должен заниматься проверкой статуса requiredService, он просто передает его дальше. То же самое с обратным вызовом.
- Если вам потребуется перезагрузить службу ( удалить внешнее if в setRequiredService ), вам не нужно будет изменять логику в конструкторе и т.д..