AuraPHP DI динамический класс или инъекция на основе решений

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

Это моя аура конфиг

<?php
namespace Aura\Cli_Project\_Config;

use Aura\Di\Config;
use Aura\Di\Container;

class Common extends Config {
public function define(Container $di) {
// utilities
$di->set(
'App\Inventory\Utilities\EmailParser',
$di->newInstance('App\Inventory\Utilities\PlancakeParser')
);

// commands
$di->params['App\Inventory\Command\IncomingOrder'] = array(
'stdio' => $di->lazyGet('aura/cli-kernel:stdio'),
'parser' => $di->get('App\Inventory\Utilities\EmailParser')
);
}
// ...
}

И этот класс, о котором идет речь, должен использовать разные классы в зависимости от «источника», который он находит.

<?php

namespace App\Inventory\Command;

use Aura\Cli\Stdio;
use App\Inventory\Utilities\EmailParser;
use App\Inventory\Sources\Etsy;
use App\Inventory\Sources\Amazon;
use App\Inventory\Sources\Ebay;

class IncomingOrder {

public function __construct(
Stdio $stdio,
EmailParser $parser) {
$this->stdio = $stdio;
$this->parser = $parser;
}

public function process() {
// other code to parse message
// source is set by determining where it came from
$source = 'Etsy';

switch($source) {
case 'Etsy' :
// This bit seems really wrong
$sourceParser = new Etsy\OrderParser();
break;
case 'Amazon' :
$sourceParser = new Amazon\OrderParser();
break;
case 'Ebay' :
$sourceParser = new Ebay\OrderParser();
break;
default :
$sourceParser = null;
}

// Do source specific processing
}
}

Нужно ли разделять обработку в точке сразу после определения источника, чтобы новый класс мог быть инициализирован с этим источником в качестве параметра?

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

1

Решение

Я хотел бы уточнить, что вам не нужно использовать set метод, как и многие из контейнеров ди здесь. Вы можете изменить код на

<?php
namespace Aura\Cli_Project\_Config;

use Aura\Di\Config;
use Aura\Di\Container;

class Common extends Config
{
public function define(Container $di)
{
// commands
$di->params['App\Inventory\Command\IncomingOrder'] = array(
'stdio' => $di->lazyGet('aura/cli-kernel:stdio'),
'parser' => $di->lazyNew('App\Inventory\Utilities\EmailParser')
);
}
// ...
}

Вы можете использовать set когда вы хотите передать один и тот же объект многим другим объектам. Не использовать newInstance ибо он создаст объект при вызове того же самого. Возможно, вам придется использовать lazyNew или же lazyGet Функциональные возможности.

По поводу вашего вопроса о динамическом принятии решений. Вот мои мысли, я уже сталкивался с этим вопросом некоторое время назад. Но я не видел, что я сделал, поэтому мне сделали то, что я сделал, на заводе IncomingOrder класс, который может создать объект. Хорошая вещь в этом заключается в том, что если вашему анализу исходного кода нужна какая-то зависимость, вы можете использовать di внутри фабрики.

Например:

<?php
namespace Something;

use Aura\Di\Container;

class SourceFactory
{
public function __construct(Container $di)
{
$this->di = $di;
}

public function newInstance($source)
{
if ($di->has($source)) {
return $di->get($source);
}
// or alternatively create with new as done in switch
}
}

Надеюсь, это поможет.

Спасибо

2

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

Других решений пока нет …