はじめに
初投稿です。
今まで業務ではlaravel5.5を使っており、最近新規のプロジェクトでlaravel6系統を使うようになったので、色々と変更点を確認しておりました(今更)。
その中で、ドキュメントにひっそりと追記されているにもかかわらず、あまり類似の情報をqiita等で見かけなかった(と思っている)物があったため、備忘録として投稿します。
環境
- laravel 5.6 ~
- ~ 5.5までは対応していません
対象
- Laravelをそれなりに使っていて、DIコンテナ内で抽象と具象のbindについて大枠理解している方
- 本記事ではDIの仕組み、それを使う動機等、「そもそもなぜこんなことをする必要があるか」について理解されている前提です。
基本的なバインド処理
さて、早速ですが基本的なバインド処理についてです。
最も基本的なinterfaceと実装クラスのbindingは以下のようになるかと思います。
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
// 抽象に対して具象クラスをbindingする
// 以後、コンストラクタインジェクションやapp()の引数に(Abstract::class)で呼び出すと、Concreteクラスが返却される
$this->app->bind(Abstract::class, Concrete::class);
dd(Abstract::class); // => Concreteクラスが返却される
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
}
}
~ 5.5までのバインド方法
その上で、複数のバインドをまとめて行いたいユースケースについて考えます。
今まで自分が関わってきたプロジェクトで、バインドを複数まとめて行いたいとき(Repository Pattern等)、以下のような書き方をしていました。
class AppServiceProvider extends ServiceProvider
{
/**
* bindingするinterfaceと実装クラスを$key => $valueで保持する
*
* @param array
*/
private $repositoryBindings = [
FooRepository::class => EloquentFooRepository::class,
BarRepository::class => EloquentBarRepository::class,
];
/**
* Register any application services.
*
* @return void
*/
public function register()
{
// すべてのbindingを回して登録する
foreach($repositoryBindings as $abstract => $concrete) {
$this->app->bind($abstract => $concrete);
}
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
}
}
汚いというわけでもなく、特に問題なく動作するコードです。
5.6からのバインド方法
readoubleにしれっと追記されています。
https://readouble.com/laravel/5.6/ja/providers.html
シンプルなバインドを行うためのプロパティが追加されており、ここにbindを指定するだけで自動でbindingが行われる様になっています。
(ついでに$singletonのプロパティも用意されています)
class AppServiceProvider extends ServiceProvider
{
/**
* 結合したいabstractとconcreteを登録. ここに記述されたものは自動でbindingされる
*
* @param array
*/
public $bindings = [
FooRepository::class => EloquentFooRepository::class,
BarRepository::class => EloquentBarRepository::class,
];
/**
* Register any application services.
*
* @return void
*/
public function register()
{
// ここで何も書かなくても$bindingsに指定があれば自動でbindが行われる
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
}
}
終わりに
大きなメリットがあるわけでもなく、ちょっとしたtipsでした。
ただ、やはりフレームワークが用意してくれている方式に乗っかれると気持ちがいいですね。