서비스 컨테이너
ㅋㅋ
- 기본 바인딩
- 싱글톤 바인딩
- 인스턴스 바인딩 컨테이너 이벤트
- PSR 주입 -11
- 태그
- 확장 바인딩
- 파싱
- In troduction
- Laravel 서비스 컨테이너는 클래스 관리를 위한 강력한 도구입니다. 종속성 및 종속성 주입 수행. 종속성 주입이라는 멋진 용어는 본질적으로 클래스의 종속성이 생성자 또는 경우에 따라 "setter" 메서드를 통해 클래스에 "주입"된다는 것을 의미합니다. 간단한 예를 살펴보겠습니다.
<?php namespace App\Http\Controllers; use App\User; use App\Repositories\UserRepository; use App\Http\Controllers\Controller; class UserController extends Controller{ /** * 用户存储库的实现. * * @var UserRepository */ protected $users; /** * 创建新的控制器实例. * * @param UserRepository $users * @return void */ public function __construct(UserRepository $users) { $this->users = $users; } /** * 显示指定用户的 profile. * * @param int $id * @return Response */ public function show($id) { $user = $this->users->find($id); return view('user.profile', ['user' => $user]); } }
- 이 예에서 컨트롤러
UserController
는 데이터 소스에서 사용자를 가져와야 합니다. 따라서 사용자를 확보할 수 있는 서비스를 삽입해야 합니다. 현재 상황에서UserRepository
는 데이터베이스에서 사용자 정보를 얻기 위해 Eloquent를 사용하고 있을 가능성이 높습니다. 그러나 저장소가 주입되므로 다른 구현으로 쉽게 전환할 수 있습니다. 이 주입 방법의 편리함은 애플리케이션에 대한 테스트를 작성할 때UserRepository
의 가상 구현을 쉽게 "모의"하거나 생성할 수도 있다는 것입니다. 강력한 대규모 애플리케이션을 구축하려면 한 가지 중요한 것이 있습니다. 바로 Laravel 서비스 컨테이너에 대한 깊은 이해입니다. 물론 Laravel의 핵심 코드에 기여하는 경우에도 마찬가지입니다.
- 서비스 바인딩
기본 바인딩
대부분의 사용자 서비스 컨테이너가 서비스에 등록되어 있으므로 따라서 아래의 대부분의 예에서는 서비스 공급자 내에서 컨테이너를 사용하는 방법을 보여줍니다.
- 간단한 바인딩
간단한 바인딩
서비스 제공자에서는$this->app
속성을 통해 언제든지 컨테이너에 액세스할 수 있습니다. 컨테이너의 bind
메소드를 통해 바인딩을 등록할 수 있습니다. bind
메소드의 첫 번째 매개변수는 바인딩할 클래스/인터페이스 이름이고 두 번째 매개변수는 반환값입니다. class.클로저
의 예: $this->app->bind('HelpSpot\API', function ($app) { return new HelpSpot\API($app->make('HttpClient')); });우리는 컨테이너 자체를 파서에 대한 매개변수로 받아들입니다. 그런 다음 컨테이너를 사용하여 빌드 중인 개체의 하위 종속성을 해결할 수 있습니다.
싱글톤 바인딩
싱글톤
메서드는 클래스나 인터페이스를 한 번만 확인되는 컨테이너에 바인딩합니다. 싱글톤 바인딩이 해결되면 후속 호출 시 동일한 객체 인스턴스가 컨테이너에 반환됩니다. $this->app->singleton('HelpSpot\API', function ($app) { return new HelpSpot\API($app->make('HttpClient')); });
인스턴스 바인딩
instance
메서드를 사용하여 기존 개체 인스턴스를 컨테이너에 바인딩할 수도 있습니다. 주어진 인스턴스는 후속 호출에서 항상 컨테이너로 반환됩니다. instance
方法将现有对象实例绑定到容器中。给定的实例会始终在随后的调用中返回到容器中:
$api = new HelpSpot\API(new HttpClient); $this->app->instance('HelpSpot\API', $api);
绑定基本值
当你有一个类不仅需要接受一个注入类,还需要注入一个基本值(比如整数)。你可以使用上下文绑定来轻松注入你的类需要的任何值:
$this->app->when('App\Http\Controllers\UserController') ->needs('$variableName') ->give($value);
绑定接口到实现
服务容器有一个很强大的功能,就是支持绑定接口到给定的实现。例如,如果我们有个 EventPusher
接口 和一个 RedisEventPusher
实现。一旦我们写完了 EventPusher
接口的 RedisEventPusher
实现,我们就可以在服务容器中注册它,像这样:
$this->app->bind( 'App\Contracts\EventPusher', 'App\Services\RedisEventPusher' );
这么做相当于告诉容器:当一个类需要实现 EventPusher
时,应该注入 RedisEventPusher
。现在我们就可以在构造函数或者任何其他通过服务容器注入依赖项的地方使用类型提示注入 EventPusher
接口:
use App\Contracts\EventPusher; /** * Create a new class instance. * * @param EventPusher $pusher * @return void */ public function __construct(EventPusher $pusher){ $this->pusher = $pusher; }
上下文绑定
有时你可能有两个类使用了相同的接口,但你希望各自注入不同的实现。例如, 有两个控制器可能依赖了 IlluminateContractsFilesystemFilesystem
契约. Laravel 提供了一个简单的,优雅的接口来定义这个行为:
use Illuminate\Support\Facades\Storage; use App\Http\Controllers\PhotoController; use App\Http\Controllers\VideoController; use Illuminate\Contracts\Filesystem\Filesystem; $this->app->when(PhotoController::class) ->needs(Filesystem::class) ->give(function () { return Storage::disk('local'); }); $this->app->when([VideoController::class, UploadController::class]) ->needs(Filesystem::class) ->give(function () { return Storage::disk('s3'); });
标记
有时候,你可能需要解析某个 “分类” 下的所有绑定。 比如, 你可能正在构建一个报表的聚合器,它接收一个包含不同 Report
接口实现的数组。注册 Report
实现之后,你可以使用 tag
方法给他们分配一个标签:
$this->app->bind('SpeedReport', function () { // }); $this->app->bind('MemoryReport', function () { // }); $this->app->tag(['SpeedReport', 'MemoryReport'], 'reports');
一旦服务被标记,你就可以通过 tagged
方法轻松地解析它们:
$this->app->bind('ReportAggregator', function ($app) { return new ReportAggregator($app->tagged('reports')); });
扩展绑定
extend
方法可以修改已解析的服务。比如,当一个服务被解析后,你可以添加额外的代码来修饰或者配置它。 extend
方法接受一个闭包,该闭包唯一的参数就是这个服务, 并返回修改过的服务:
$this->app->extend(Service::class, function ($service) { return new DecoratedService($service); });
解析实例
make
方法
你可以使用 make
方法从容器中解析出类实例。 make
方法接收你想要解析的类或接口的名字:
$api = $this->app->make('HelpSpot\API');
如果你的代码处于无法访问 $app
变量的位置,则可用全局辅助函数 resolve
来解析:
$api = resolve('HelpSpot\API');
如果类依赖不能通过容器解析,你可以通过将它们作为关联数组作为 makeWith
$api = $this->app->makeWith('HelpSpot\API', ['id' => 1]);기본 값 바인딩
주입된 클래스를 수락해야 할 뿐만 아니라 기본 값도 주입해야 하는 클래스가 있는 경우(예: 정수). 컨텍스트 바인딩을 사용하면 클래스에 필요한 값을 쉽게 주입할 수 있습니다.
<?php namespace App\Http\Controllers; use App\Users\Repository as UserRepository; class UserController extends Controller{ /** * The user repository instance. */ protected $users; /** * Create a new controller instance. * * @param UserRepository $users * @return void */ public function __construct(UserRepository $users) { $this->users = $users; } /** * Show the user with the given ID. * * @param int $id * @return Response */ public function show($id) { // } }🎜🎜
인터페이스를 구현에 바인딩
🎜Service 매우 강력한 기능 컨테이너의 장점은 주어진 구현에 대한 바인딩 인터페이스를 지원한다는 것입니다. 예를 들어EventPusher
인터페이스와 RedisEventPusher
구현이 있는 경우입니다. EventPusher
인터페이스의 RedisEventPusher
구현을 작성한 후에는 다음과 같이 이를 서비스 컨테이너에 등록할 수 있습니다. 🎜$this->app->resolving(function ($object, $app) { // Called when container resolves object of any type... }); $this->app->resolving(HelpSpot\API::class, function ($api, $app) { // Called when container resolves objects of type "HelpSpot\API"... });🎜이것은 컨테이너에 다음과 같이 알려주는 것과 같습니다. 클래스
EventPusher
를 구현해야 하는 경우 RedisEventPusher
를 삽입해야 합니다. 이제 유형 힌트를 사용하여 생성자 또는 서비스 컨테이너를 통해 종속성이 주입되는 다른 위치에 EventPusher
인터페이스를 주입할 수 있습니다. h3> 컨텍스트 바인딩🎜때때로 동일한 인터페이스를 사용하는 두 개의 클래스가 있을 수 있지만 각각에 다른 구현을 주입하고 싶을 수도 있습니다. 예를 들어, 두 개의 컨트롤러가 IlluminateContractsFilesystemFilesystem
계약에 의존할 수 있습니다. Laravel은 이 동작을 정의하기 위한 간단하고 우아한 인터페이스를 제공합니다: 🎜use Psr\Container\ContainerInterface; Route::get('/', function (ContainerInterface $container) { $service = $container->get('Service'); // });🎜🎜🎜
Mark h3>🎜때때로 특정 "범주" 아래의 모든 바인딩을 구문 분석해야 할 수도 있습니다. 예를 들어, 보고서
인터페이스의 다양한 구현 배열을 수신하는 보고서 수집기를 구축할 수 있습니다. 보고서
구현을 등록한 후 tag
메서드를 사용하여 태그를 할당할 수 있습니다. 🎜rrreee🎜서비스에 태그가 지정되면 tagged<를 통해 할당할 수 있습니다. /code> 쉽게 구문 분석하는 방법: 🎜rrreee🎜🎜🎜바인딩 확장
🎜extend
방법은 확인된 서비스를 수정할 수 있습니다. 예를 들어 서비스가 해결된 후 추가 코드를 추가하여 이를 장식하거나 구성할 수 있습니다. extend
메소드는 유일한 매개변수가 서비스인 클로저를 받아들이고 수정된 서비스를 반환합니다: 🎜rrreee🎜🎜🎜인스턴스 분석 중
🎜< a name="the-make-method">🎜🎜🎜make
메서드 🎜🎜 make
메서드를 사용하여 컨테이너에서 클래스 인스턴스를 확인할 수 있습니다. make
메소드는 해결하려는 클래스 또는 인터페이스의 이름을 받습니다. 🎜rrreee🎜코드가 $app
변수에 액세스할 수 없는 위치에 있는 경우 전역 도우미 함수resolve
를 사용하여 다음을 해결할 수 있습니다. 🎜rrreee🎜클래스 종속성을 컨테이너에서 해결할 수 없는 경우 이를 makeWith
방법: 🎜rrreee🎜🎜🎜🎜자동 주입
또한 더 중요한 점은 컨트롤러, 이벤트 리스너, 대기열 작업, 미들웨어 등을 포함하여 클래스 생성자의 컨테이너에서 해결해야 하는 종속성을 간단히 "유형 힌트"를 사용하여 주입할 수 있다는 것입니다. . 실제로 컨테이너가 대부분의 개체를 해결하는 방법은 다음과 같습니다.
예를 들어 컨트롤러 생성자에 저장소 유형 힌트를 추가하면 저장소가 자동으로 구문 분석되어 클래스에 주입됩니다.
rrreeeContainer events
서비스 컨테이너가 객체를 구문 분석할 때마다 이벤트를 트리거하면 resolving
메서드를 사용하여 이 이벤트를 수신할 수 있습니다. resolving
方法监听这个事件 :
rrreee正如你所看到的,被解析的对象将会被传入回调函数,这使得你能够在对象被传给调用者之前给它设置额外的属性。
PSR-11
Laravel 的服务容器实现了 PSR-11 接口。因此,你可以使用 PSR-11 容器 『接口类型提示』 来获取 Laravel 容器的实例:
rrreee如果无法解析给定的标识符,则将会引发异常。未绑定标识符时,会抛出 PsrContainerNotFoundExceptionInterface
异常。如果标识符已绑定但无法解析,会抛出 PsrContainerContainerExceptionInterface
rrreee
보시다시피 구문 분석된 객체는 콜백 함수에 전달되며 이를 통해 추가 속성을 설정할 수 있습니다. 호출자에게 전달하기 전에.
바인딩 확장
🎜extend
방법은 확인된 서비스를 수정할 수 있습니다. 예를 들어 서비스가 해결된 후 추가 코드를 추가하여 이를 장식하거나 구성할 수 있습니다. extend
메소드는 유일한 매개변수가 서비스인 클로저를 받아들이고 수정된 서비스를 반환합니다: 🎜rrreee🎜🎜🎜인스턴스 분석 중
🎜< a name="the-make-method">🎜🎜🎜make
메서드 🎜🎜 make
메서드를 사용하여 컨테이너에서 클래스 인스턴스를 확인할 수 있습니다. make
메소드는 해결하려는 클래스 또는 인터페이스의 이름을 받습니다. 🎜rrreee🎜코드가 $app
변수에 액세스할 수 없는 위치에 있는 경우 전역 도우미 함수resolve
를 사용하여 다음을 해결할 수 있습니다. 🎜rrreee🎜클래스 종속성을 컨테이너에서 해결할 수 없는 경우 이를 makeWith
방법: 🎜rrreee🎜🎜🎜🎜자동 주입
또한 더 중요한 점은 컨트롤러, 이벤트 리스너, 대기열 작업, 미들웨어 등을 포함하여 클래스 생성자의 컨테이너에서 해결해야 하는 종속성을 간단히 "유형 힌트"를 사용하여 주입할 수 있다는 것입니다. . 실제로 컨테이너가 대부분의 개체를 해결하는 방법은 다음과 같습니다.
예를 들어 컨트롤러 생성자에 저장소 유형 힌트를 추가하면 저장소가 자동으로 구문 분석되어 클래스에 주입됩니다.
rrreeeContainer events
서비스 컨테이너가 객체를 구문 분석할 때마다 이벤트를 트리거하면 resolving
메서드를 사용하여 이 이벤트를 수신할 수 있습니다. resolving
方法监听这个事件 :
正如你所看到的,被解析的对象将会被传入回调函数,这使得你能够在对象被传给调用者之前给它设置额外的属性。
PSR-11
Laravel 的服务容器实现了 PSR-11 接口。因此,你可以使用 PSR-11 容器 『接口类型提示』 来获取 Laravel 容器的实例:
rrreee如果无法解析给定的标识符,则将会引发异常。未绑定标识符时,会抛出 PsrContainerNotFoundExceptionInterface
异常。如果标识符已绑定但无法解析,会抛出 PsrContainerContainerExceptionInterface
rrreee
PsrContainerNotFoundExceptionInterface
예외가 발생합니다. 식별자가 바인딩되었지만 확인할 수 없는 경우 PsrContainerContainerExceptionInterface
예외가 발생합니다. 🎜🎜이 글은 🎜LearnKu.com🎜 웹사이트에 처음 게시되었습니다. 🎜🎜