如何在 Laravel 控制器方法中不使用容器?
How not to use the container within Laravel controller method?
我已经开始研究 Laravel 并且我对项目中的依赖项管理有一些疑问。假设我有依赖
DependencyA
使用 DependencyB
使用 DependencyC
:
<?php
namespace Some\NamespaceOf;
use Illuminate\Container\Container;
class DependencyA {
public function someMethod(DependencyB $b, Container $container) {
$container->call([$b, 'doSomething']);
}
}
class DependencyB {
public function doSomething(DependencyC $c) {
// ... do something with $c
}
}
然后,在我的控制器中:
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
use Some\NamespaceOf\DependencyA;
use Illuminate\Container\Container;
class SomeController extends Controller
{
// ...
/**
* @param DependencyA $a
* @return Response
*/
public function controllerMethod(DependencyA $a, Container $container)
{
$container->call([$a, 'someMethod']);
// ...
}
// ...
}
我不喜欢在组件之间反复传递控制器。
在这种情况下最好的重构是什么?将控制器重写为:
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
use Some\NamespaceOf\DependencyA;
use Some\NamespaceOf\DependencyB;
use Illuminate\Container\Container;
class SomeController extends Controller
{
// ...
/**
* @param DependencyA $a
* @return Response
*/
public function controllerMethod(DependencyA $a, DependencyB $b)
{
$a->someMethod($b);
// ...
}
// ...
}
这还不够,因为 DependencyA
还需要容器在调用 $b->doSomething()
传递它 $c
之前查找 DependencyC
。我也必须编辑 DependencyA
,但是我怎样才能向它注入 DependencyC
?
这种依赖关系形成时应该怎么办?
在组件中使用容器让我觉得违反了 IoC
原则。
感谢关注
如果我懂你;这可能会有帮助:
AppServiceProvider:
namespace App\Providers;
use App\Dependencies\DependencyA;
use App\Dependencies\DependencyB;
use App\Dependencies\DependencyC;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->app->bind(DependencyB::class, function ($app) {
return new DependencyB(new DependencyC());
});
$this->app->bind(DependencyA::class, function ($app) {
return new DependencyA($app->make(DependencyB::class));
});
}
}
DependencyA:
namespace App\Dependencies;
class DependencyA
{
private $dependencyB;
public function __construct(DependencyB $dependencyB)
{
$this->dependencyB = $dependencyB;
}
public function useMe()
{
return $this->dependencyB->useMe();
}
}
DependencyB:
namespace App\Dependencies;
class DependencyB
{
private $dependencyC;
public function __construct(DependencyC $dependencyC)
{
$this->dependencyC = $dependencyC;
}
public function useMe()
{
return $this->dependencyC->useMe();
}
}
DependencyC:
namespace App\Dependencies;
class DependencyC
{
public function useMe()
{
echo "Used me.";
}
}
现在,在我们的控制器中,如果我们使用 DependencyA 作为唯一的依赖; DependencyA class 和 DependencyB class 的依赖关系将被分别解析。
DependantController:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Dependencies\DependencyA;
class DependantController extends Controller
{
private $dependencyA;
public function __construct(DependencyA $dependencyA)
{
$this->dependencyA = $dependencyA;
}
public function index()
{
$this->dependencyA->useMe();
}
}
web.php
Route::get('dependant', 'DependantController@index');
现在,如果您访问http://127.0.0.1:8000/dependant
您将看到 Used me.
作为此实施的结果。
我已经开始研究 Laravel 并且我对项目中的依赖项管理有一些疑问。假设我有依赖
DependencyA
使用 DependencyB
使用 DependencyC
:
<?php
namespace Some\NamespaceOf;
use Illuminate\Container\Container;
class DependencyA {
public function someMethod(DependencyB $b, Container $container) {
$container->call([$b, 'doSomething']);
}
}
class DependencyB {
public function doSomething(DependencyC $c) {
// ... do something with $c
}
}
然后,在我的控制器中:
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
use Some\NamespaceOf\DependencyA;
use Illuminate\Container\Container;
class SomeController extends Controller
{
// ...
/**
* @param DependencyA $a
* @return Response
*/
public function controllerMethod(DependencyA $a, Container $container)
{
$container->call([$a, 'someMethod']);
// ...
}
// ...
}
我不喜欢在组件之间反复传递控制器。
在这种情况下最好的重构是什么?将控制器重写为:
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
use Some\NamespaceOf\DependencyA;
use Some\NamespaceOf\DependencyB;
use Illuminate\Container\Container;
class SomeController extends Controller
{
// ...
/**
* @param DependencyA $a
* @return Response
*/
public function controllerMethod(DependencyA $a, DependencyB $b)
{
$a->someMethod($b);
// ...
}
// ...
}
这还不够,因为 DependencyA
还需要容器在调用 $b->doSomething()
传递它 $c
之前查找 DependencyC
。我也必须编辑 DependencyA
,但是我怎样才能向它注入 DependencyC
?
这种依赖关系形成时应该怎么办?
在组件中使用容器让我觉得违反了 IoC
原则。
感谢关注
如果我懂你;这可能会有帮助:
AppServiceProvider:
namespace App\Providers;
use App\Dependencies\DependencyA;
use App\Dependencies\DependencyB;
use App\Dependencies\DependencyC;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->app->bind(DependencyB::class, function ($app) {
return new DependencyB(new DependencyC());
});
$this->app->bind(DependencyA::class, function ($app) {
return new DependencyA($app->make(DependencyB::class));
});
}
}
DependencyA:
namespace App\Dependencies;
class DependencyA
{
private $dependencyB;
public function __construct(DependencyB $dependencyB)
{
$this->dependencyB = $dependencyB;
}
public function useMe()
{
return $this->dependencyB->useMe();
}
}
DependencyB:
namespace App\Dependencies;
class DependencyB
{
private $dependencyC;
public function __construct(DependencyC $dependencyC)
{
$this->dependencyC = $dependencyC;
}
public function useMe()
{
return $this->dependencyC->useMe();
}
}
DependencyC:
namespace App\Dependencies;
class DependencyC
{
public function useMe()
{
echo "Used me.";
}
}
现在,在我们的控制器中,如果我们使用 DependencyA 作为唯一的依赖; DependencyA class 和 DependencyB class 的依赖关系将被分别解析。
DependantController:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Dependencies\DependencyA;
class DependantController extends Controller
{
private $dependencyA;
public function __construct(DependencyA $dependencyA)
{
$this->dependencyA = $dependencyA;
}
public function index()
{
$this->dependencyA->useMe();
}
}
web.php
Route::get('dependant', 'DependantController@index');
现在,如果您访问http://127.0.0.1:8000/dependant
您将看到 Used me.
作为此实施的结果。