テストしてみましょう:
app/Http/routes.php< ?phpclass Bar{}class Foo{ public $bar; public function __construct( Bar $bar) //Foo这个class的构造函数里要传入Bar $bar,一层接着一层,一般情况下,我们需要不断的 new实例,解决所有的依赖 //但是laravel会帮你自动去解析和new实例化,很容易可以感觉到这是一种很大的便利。 { $this->bar = $bar; }}Route::get('/', function (Foo $foo) { //这里其实不算是依赖注入,依赖注入是面向接口的,这里只是一个很像依赖注入的东西,这个就是laravel的IOC container //laravel会尝试去解析Foo $foo这种语义,解析其实就是去查找是否有这样的class或者其他东西,有就会放到这里 //这里解析到这是一个Foo的class dd($foo);});
実際、laravel はここで PHP のリフレクションを借用しています
PHP5 には、リフレクションという新しい機能が追加されています。この機能により、PHP はクラス、インターフェイス、関数、メソッド、拡張機能をリバース エンジニアリングできるようになります。 PHP コードを通じて、オブジェクトのすべての情報を取得し、オブジェクトと対話できます。
リフレクションとは何ですか?
PHP プログラムの実行状態での解析を拡張し、クラス、メソッド、プロパティ、パラメータなどの詳細情報をコメントも含めてエクスポートまたは抽出することを指します。この動的に情報を取得し、オブジェクトのメソッドを動的に呼び出す機能をリフレクションAPIと呼びます。リフレクションは、オブジェクト指向パラダイムでメタモデルを操作するための API であり、非常に強力で、複雑でスケーラブルなアプリケーションの構築に役立ちます。
< ?phpclass Bar{}class Foo{ public $bar; public function __construct( Bar $bar) { $this->bar = $bar; }}App::bind('Foo',function(){ // laravel提供了bind的方法来注册binding,通过class或者interface名字(解析一起传递的闭包)来返回一个实例,功能上类似之前的自动查找和解析 //不过如果使用了bind的话,那么会优先使用bind的方法,而不会再去自动查找和解析 //这里就会先出现 “call here” dd('call here'); return new Foo(new Bar());});Route::get('/', function (Foo $foo) { dd($foo);});
laravel のドキュメントには非常に重要な点が記載されています。コンテナ自体を引数として受け取ることに注意してください。次に、コンテナを使用して、構築しているオブジェクトのサブ依存関係を解決します。コンテナを受け取り、それ自体をパラメータとして解決し、それを構築中のオブジェクトのサブ依存関係を解決するために使用できます。これは、すべての依存関係をコンテナーに引き渡すことと同じであり、コンテナーを分析するだけで済みます。
詳細は、https://laravel.com/docs/5.2/container
サービスプロバイダーは次の目的で使用されます。関連するサービス コンテナは、統合されたバインディング場所を提供します。さらに、サービス プロバイダーはいくつかの初期化および起動操作を実行することもできます。 Laravel の各コア コンポーネントはサービス プロバイダーに対応しており、サービス プロバイダーは Laravel の中心であり、以降の呼び出しのためにここでコア コンポーネント クラスが登録および初期化されます。
城、執事、奴隷
むかしむかし、この城には働く奴隷を管理する大きな執事がいました。
シーン 1.
城は順調に進んでおり、来客が増えています。執事は、誰もが楽に過ごせるように城内に交通手段が必要だと考えています。旅行する。そこで彼は馬を買いに行き、それを奴隷に与え、奴隷にこう言いました。
もし客が将来交通手段を必要とするなら、この馬を彼に渡してください。
シーン 2.
城はますます良くなり、家政婦はより多くのお金を持っていますが、馬は遅すぎて乗り心地が悪いと感じています。彼は再び奴隷に、次回顧客が交通手段を必要とするときは、東方路にあるメルセデス・ベンツ 4S 店に行き、メルセデス・ベンツ C クラスを買って顧客に持ち帰るようにと言いました。
シーン 3.
ある日、外国の高官を城に迎えることになり、メルセデス・ベンツはもう高級ではなくなったため、ロールス・ロイスを買わなければなりませんでした。執事は奴隷にこう言った「もしこの高官が必要なら、旅行に行くときはロールスロイスを買って帰ってくるが、何度頼んでもその車しか使えず、二台目(車)は買えない」高すぎる)。
引用リンク: http://jingpin.jikexueyuan.com/article/44059.html
これは公式 Web サイトのドキュメント サービス プロバイダーの例です
< ?phpnamespace App\Providers;use Riak\Connection;use Illuminate\Support\ServiceProvider;class RiakServiceProvider extends ServiceProvider{ /** * Register bindings in the container. * * @return void */ public function register() //register方法是service provider独有的,固定语法 { $this->app->singleton(Connection::class, function ($app) { //这里看到这个就是一个container的绑定写法,使用的是singleton方法,service provider管理container return new Connection(config('riak')); }); }}
シングルトンメソッド
$this->app->singleton('FooBar', function ($app) { //singleton方法会绑定一个class或者interface名字到一个container里,然后在随后的调用返回同一个实例 return new FooBar($app['SomethingElse']); //这里绑定的是FooBar这个class的名,然后在这里返回了一个一样的FooBar实例});
vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemServiceProvider.php< ?phpnamespace Illuminate\Filesystem;use Illuminate\Support\ServiceProvider;class FilesystemServiceProvider extends ServiceProvider{ /** * Register the service provider. * * @return void */ public function register() //一样是有register方法 { $this->registerNativeFilesystem(); //调用了一个本地方法 $this->registerFlysystem(); } /** * Register the native filesystem implementation. * * @return void */ protected function registerNativeFilesystem() //就是这个,而这个方法使用了singleton,绑定了一个files,但是返回的FileSystem名字却不是一样, //singleton其实是做了类似映射的处理,将files跟new Filesystem进行绑定关系,我们在访问files的时候就顺理成章地访问new Filesystem { $this->app->singleton('files', function () { return new Filesystem; }); } 省略..............
サービスプロバイダー、サービスについて上記で説明したものプロバイダー自体は実際にはコンテナー マネージャーと同等であり、コンテナーの管理を容易にしますが、コアの呼び出しは依然としてコンテナーです。
$fooBar = $this->app->make('FooBar'); //用make方法,这个是属于container的make方法,make接受的参数是make(string $abstract, array $parameters = array()), //主要用来从container中解析给定的信息,返回一个container的实例$fooBar = $this->app['FooBar']; //用传入数组的方法
これらの利用方法はソースコードを見ることで理解できます
vendor/laravel/framework/src/Illuminate/Foundation/helpers.phpif (! function_exists('app')) { /** * Get the available container instance. * * @param string $make * @param array $parameters * @return mixed|\Illuminate\Foundation\Application */ function app($make = null, $parameters = []) { if (is_null($make)) { return Container::getInstance(); //会返回一个container的实例 } return Container::getInstance()->make($make, $parameters); }}
引用参考:https://laravel.com/docs/5.2/container#
を解決しています