gpt4 book ai didi

php - (Laravel) 基于用户输入的接口(interface)动态依赖注入(inject)

转载 作者:IT王子 更新时间:2023-10-29 00:08:04 26 4
gpt4 key购买 nike

我目前在架构和实现方面面临一个非常有趣的困境。

我有一个名为 ServiceInterface 的接口(interface),它有一个名为 execute() 的方法

然后我对该接口(interface)有两个不同的实现:Service1Service2,它们正确地实现了 execute 方法。

我有一个名为 MainController 的 Controller ,这个 Controller 有一个针对 ServiceInterface 的“类型提示”(依赖注入(inject)),这意味着Service1Service2 都可以调用作为该依赖项注入(inject)的解决方案。

现在是有趣的部分:

我不知道要使用这些实现中的哪一个(Service1Service2),因为我只知道我是否可以根据用户使用一个或其他实现来自上一步的输入

这意味着用户选择了一项服务,并且根据该值我知道是否可以使用 Service1Service2

我目前正在使用 session 值解决依赖注入(inject),因此根据返回实例或其他实例的值,但我真的认为这不是一个好方法。

如果您遇到类似的事情,请告诉我,您是如何解决的,或者我该怎么做才能以正确的方式实现这一目标。

提前致谢。如果需要更多信息,请告诉我。

最佳答案

最后,经过几天的研究和思考,使用 Laravel 的最佳方法,我终于解决了。

我不得不说这在 Laravel 5.2 中特别困难,因为在这个版本中,Session 中间件仅在路由中使用的 Controller 中执行,它意味着如果由于某种原因我使用了 Controller (未链接到死记硬背)并尝试访问 session ,这将是不可能的。

所以,因为我不能使用 session ,所以我决定使用 URL 参数。在这里,您有解决方法;我希望你们中的一些人觉得它有用。

所以,你有一个界面:

interface Service
{
public function execute();
}

然后是接口(interface)的几个实现:

服务一:

class ServiceOne implements Service
{
public function execute()
{
.......
}
}

服务二。

class ServiceTwo implements Service
{
public function execute()
{
.......
}
}

有趣的部分是我有一个 Controller ,它的函数依赖于 Service 接口(interface)。不过,我需要根据用户输入将其动态解析为 ServiceOne 或 ServiceTwo。所以:

Controller

class MyController extends Controller
{
public function index(Service $service, ServiceRequest $request)
{
$service->execute();
.......
}
}

请注意ServiceRequest,验证请求已经有我们需要解析依赖的参数(称之为'service_name')

现在,在 AppServiceProvider 中我们可以这样解决依赖:

class AppServiceProvider extends ServiceProvider
{
public function boot()
{

}

public function register()
{
//This specific dependency is going to be resolved only if
//the request has the service_name field stablished
if(Request::has('service_name'))
{
//Obtaining the name of the service to be used (class name)
$className = $this->resolveClassName(Request::get('service_name')));

$this->app->bind('Including\The\Namespace\For\Service', $className);
}
}

protected function resolveClassName($className)
{
$resolver = new Resolver($className);
$className = $resolver->resolveDependencyName();
return $className;
}
}

所以现在所有的责任都交给了 Resolver 类。这个类基本上使用传递给构造函数的参数来返回将用作服务接口(interface)实现的类的全名(带命名空间):

class Resolver
{
protected $name;
public function __construct($className)
{
$this->name = $className;
}

public function resolveDependencyName()
{
//This is just an example, you can use whatever as 'service_one'
if($this->name === 'service_one')
{
return Full\Namespace\For\Class\Implementation\ServiceOne::class;
}

if($this->name === 'service_two')
{
return Full\Namespace\For\Class\Implementation\ServiceTwo::class;
}
//If none, so throw an exception because the dependency can not be resolved
throw new ResolverException;
}
}

好吧,我真的希望它对你们中的一些人有所帮助。

祝你好运!

--------- 编辑 ------------

我只是意识到直接在 Laravel 的容器中使用请求数据并不是一个好主意。从长远来看,这确实会造成一些麻烦。

最好的方法是直接注册所有可能支持的实例(serviceone 和 servicetwo),然后直接从 Controller 或中间件解析其中一个,那么 Controller “谁决定”使用什么服务(来自所有可用)基于请求的输入。

最后,它的工作原理是一样的,但它会让你更自然地工作。

我要感谢 rizqi,来自 Laravel 闲聊问题 channel 的用户。

他亲手打造了金色article对这个。请阅读它,因为它以非常正确的方式彻底解决了这个问题。

laravel registry pattern

关于php - (Laravel) 基于用户输入的接口(interface)动态依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36853791/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com