laravel 服務容器
阿新 • • 發佈:2018-11-06
我理解的服務容器就是一個自動產生類的工廠。
<?php /** * 為了約束我們先定義一個訊息介面 * Interface Message */ interface Message{ public function seed(); } /** * 有一個傳送郵件的類 * Class SeedEmail */ class SeedEmail implements Message { public function seed() { return 'seed email'; // TODO: Implement seed() method.} } /** *新增一個傳送簡訊的類 * Class SeedSMS */ class SeedSMS implements Message { public function seed() { return 'seed sms'; // TODO: Implement seed() method. } } /** * 這是一個簡單的服務容器 * Class Container */ class Container { protected $binds; protected $instances;public function bind($abstract, $concrete) { if ($concrete instanceof Closure) { $this->binds[$abstract] = $concrete; } else { $this->instances[$abstract] = $concrete; } } public function make($abstract, $parameters = []) {if (isset($this->instances[$abstract])) { return $this->instances[$abstract]; } array_unshift($parameters, $this); return call_user_func_array($this->binds[$abstract], $parameters); } } //建立一個訊息工廠 $message = new Container(); //將傳送簡訊註冊繫結到工廠裡面 $message->bind('SMS',function (){ return new SeedSMS(); }); //將傳送郵件註冊繫結到工廠 $message->bind('EMAIL',function (){ return new SeedEmail(); }); //需要傳送簡訊的時候 $SMS = $message->make('SMS'); $SMS->seed();
container是一個簡單的服務容器裡面有bind,make兩個方法
bind是向容器中繫結服務物件。make則是從容器中取出物件。
bind
在bind方法中需要傳入一個 concrete 我們可以傳入一個例項物件或者是一個閉包函式。
可以看到我這全使用的是閉包函式,其實也可以這樣寫
$sms = new SeedSMS();
$message->bind('SMS',$sms);
後面這種寫法與閉包相比的區別就是我們需要先例項化物件才能往容易中繫結服務。而閉包則是我們使用這個服務的時候才去例項化物件。可以看出閉包是有很多的優勢的。
make
make方法就從容器中出去方法。裡面首先判斷了instances變數中是否有當前以及存在的服務物件,如果有直接返回。如果沒有那麼會通過 call_user_func_array返回一個物件。call_user_func_array的使用可以檢視
PHP 中 call_user_func 的使用