0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Laravelのサービスコンテナとは

Last updated at Posted at 2022-03-30

Laravelのサービスコンテナとは

サービスコンテナとは

DI(依存性の注入)を手助けしてくれるツール

主なサービスコンテナの機能

  1. 依存解決

    コンストラクタで型宣言したクラスを自動でインスタンス化して渡してくれる。

    まじで魔法。どうなってんの。

  2. 結合

    インスタンス化方法をカスタマイズできる

    app()->bind('呼び出しキーワード', 'インスタンス化方法');
    

結合とは

以下のようにbindメソッドによるインスタンス化方法の記述のこと。

返す値はinterfaceか実際に生成されるインスタンス(インスタンスの場合singletonでの記述をよく見る気がするので、インスタンスを返すのならそちらのほうがいいのかもしれない)

app()->bind(ClassA::class, function ($app) {
    $classB = $app()->make(ClassB::class);
    return $classB;
});

以下のようにFacadeを使ってproxy化した形で使用することもできる。

App::bind(Request::class, function ($app) {
    // Requestクラスの呼び出しをカスタマイズ
});

ファサード(Facade)とは

サービスコンテナ内の基礎となるクラスへの「静的プロキシ」として機能する。

静的プロキシとは?

プロキシパターン(Proxy Pattern)とも呼ばれる。(逆に動的プロキシもある)

(Laravelの説明なのにGoが好きなのでなぜかGoで書いてます。すいません)

type MyInterface interface {
    myMethod(string str) err;
}
type MyClass struct {
}
func (m MyClass) myMethod(string str) err {
	Println("myMethod >>>", str);
	return nil;
}

一般的なプロキシパターンを利用せずにMyClass構造体を呼び出した時(以下)

以下ではMyClassオブジェクトの利用者は実際に紐付いているmyMethod関数を使用している。

myclass := &MyClass{}
Println(myclass.myMethod("not proxy patern"));
// "myMethod >>> not proxy patern"

Proxy Paternで呼び出すには

同じinterfaceの実装を内部的にもたせればいい。

GoではnewがないのでNewMyproxyを実装するのと、その中で構造体にtargetObjをもたせてそこに実際のオブジェクトをセットするようにする。

内部のtargetObjはproxyの対象となるオブジェクトのinterface型にする。

Proxyオブジェクト経由で同じ返り値が返されるように返り値に気をつけること。

メリットとしては、本体の実装を一切変えないで機能を拡張できるというところ。

type MyProxy struct {
	proxyObj MyInterface;
}
func NewMyProxy (MyInterface wrapedObj) MyProxy {
	return &MyProxy{
		proxyObj: wrapedObj,
	}
}
func (m MyProxy) myMethod(string str) err {
	Println("myProxyMethod...");
	result := m.proxyObj.myMethod(str);
	return result;
}

Proxyの使用を強制するような実装にすることもできる。

Facadeの注意点

クラスの 「スコープクリープ」
クラスのスコープが簡単に肥大化してしまう恐れがある。ひとつのクラスを拡大することが用意であるがゆえの注意点である。

インターフェイスと実装の結合

サービスコンテナの魔法機能であるタイプヒントによるインスタンスの呼び出しもとを決定できる。

以下の例はCarInterfaceを呼び出したときに、CarClassのインスタンスを返すというもの。

つまり、以下のようなbindを行うことでCarInterfaceをコンストラクタの引数に取るクラスのインスタンスの自動生成ができるようになるということ。そして、その際に自動生成されるインスタンスはCarClassのインスタンスである。

app()->bind(CarInterface::class, CarClass::class);
class Toyota () {
	private $car;
	public function constructor(CarInterface $car){
		this->car = $car;
	}
}

Toyota Classを解決する際に効果を発揮する。

// constructorを指定せずともCarClassのインスタンスが$toyota->$carに格納される
$toyota = app()->make(Toyota::class);

参照記事

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?