Laravel5: Как внедрять зависимость в которой конструктор со своими параметрами? Работая со слоеной архитектурой, используя DI и тп. я столкнулся со следующей проблемой: К примеру есть такой код контроллера, в котором есть index экшен, который инжектит в себя MyService. Для простоты и сокращения интерфейсы не рассматриваем.get('var1'); } } Как мы знаем, laravel5 сам автоматически инжектит запрашиваемые классы из DIC. Все бы хорошо и здорово, но что если код сервиса выглядит следующим образом:data = (bool)$data; } public function getData() { return $this->data; } } Тоесть там не нужны сеттеры и в конструкторе ожидается явным образом аргумент. Соответственно при таком раскладе мы увидим ошибку примерно такого содержания:BindingResolutionException in Container.php line 849: Unresolvable dependency resolving [Parameter #0 [ $data ]] in class App\Services\MyService Да мы можем забиндить через интерфейс дефолтные данные и все такое, но что если данные которые нам нужны в конструкторе MyService, это именно те данные, которые я ожидаю получить из контроллера, тоесть $request->get('var1');Исходя из этого подскажите пожалуйста как решается подобная проблема ? Я смотрю в сторону фабрик, однако хочется получить рекомендацию и пример использования, за ранее спасибо.
Для решения данной проблемы, вам необходимо использовать фабрику (Factory) в Laravel. Фабрика предоставит возможность инъекции зависимостей с параметрами в конструкторе.
В вашем случае, вам нужно создать фабрику для сервиса MyService, которая будет возвращать экземпляр MyService с переданным параметром.
Ниже приведен пример создания фабрики для MyService:
namespace App\Services; use Illuminate\Contracts\Container\Container; class MyServiceFactory { protected $container; public function __construct(Container $container) { $this->container = $container; } public function create($data) { return $this->container->make(MyService::class, ['data' => $data]); } }
Далее вам нужно зарегистрировать эту фабрику в вашем сервис-провайдере. Например, в AppServiceProvider.php:
namespace App\Providers; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function register() { $this->app->singleton('MyServiceFactory', function ($app) { return new MyServiceFactory($app); }); } }
Теперь вы можете использовать фабрику в вашем контроллере:
namespace App\Http\Controllers; use App\Http\Requests\TestRequest; use App\Services\MyServiceFactory; class TestController extends Controller { protected $myServiceFactory; public function __construct(MyServiceFactory $myServiceFactory) { $this->myServiceFactory = $myServiceFactory; } public function index(TestRequest $request) { $data = $request->get('var1'); $myService = $this->myServiceFactory->create($data); echo $myService->getData(); } }
Теперь при вызове метода index в контроллере, данные будут передаваться в конструктор MyService с помощью фабрики.
Для решения данной проблемы, вам необходимо использовать фабрику (Factory) в Laravel. Фабрика предоставит возможность инъекции зависимостей с параметрами в конструкторе.
В вашем случае, вам нужно создать фабрику для сервиса MyService, которая будет возвращать экземпляр MyService с переданным параметром.
Ниже приведен пример создания фабрики для MyService:
namespace App\Services;use Illuminate\Contracts\Container\Container;
class MyServiceFactory
{
protected $container;
public function __construct(Container $container)
{
$this->container = $container;
}
public function create($data)
{
return $this->container->make(MyService::class, ['data' => $data]);
}
}
Далее вам нужно зарегистрировать эту фабрику в вашем сервис-провайдере. Например, в AppServiceProvider.php:
namespace App\Providers;use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton('MyServiceFactory', function ($app) {
return new MyServiceFactory($app);
});
}
}
Теперь вы можете использовать фабрику в вашем контроллере:
namespace App\Http\Controllers;use App\Http\Requests\TestRequest;
use App\Services\MyServiceFactory;
class TestController extends Controller
{
protected $myServiceFactory;
public function __construct(MyServiceFactory $myServiceFactory)
{
$this->myServiceFactory = $myServiceFactory;
}
public function index(TestRequest $request)
{
$data = $request->get('var1');
$myService = $this->myServiceFactory->create($data);
echo $myService->getData();
}
}
Теперь при вызове метода index в контроллере, данные будут передаваться в конструктор MyService с помощью фабрики.