已經有了很是好的Pimple的相關解析,建議先看下:
Pimple - 一個簡單的 PHP 依賴注入容器
讀 PHP - Pimple 源碼筆記(上)
讀 PHP - Pimple 源碼筆記(下)segmentfault
這裏經過例子補充下核心方法的說明:
相關的類型:yii2
服務(相似單例):cookie
$container['session'] = function ($c) { return new Session($c['session_storage']); };
工廠服務(多個實例)session
$container['session'] = $container->factory(function ($c) { return new Session($c['session_storage']); });
參數(僅僅是保存一些變量)dom
$container['cookie_name'] = 'SESSION_ID';
保護參數(匿名函數都會被認爲【1服務】,可是若是僅僅是想做爲一個參數,則須要用此方法)yii
$container['random_func'] = $container->protect(function () { return rand(); });
set賦值相關源碼:函數
public function offsetSet($id, $value) { //若是是被凍結,則沒法賦值 if (isset($this->frozen[$id])) { throw new FrozenServiceException($id); } //存入values $this->values[$id] = $value; //存入keys $this->keys[$id] = true; }
用【1服務】來舉例,調用offsetSet方法後:this
$this->values['session'] = function ($c) { return new Session($c['session_storage']); }; $this->keys['session'] = true;
使用時$session=$container['session'];
,此時調用offsetGet方法:code
public function offsetGet($id) { //$this->keys['session']存在 if (!isset($this->keys[$id])) { throw new UnknownIdentifierException($id); } if ( isset($this->raw[$id])//$this->raw['session'],第一次調用是沒有的,因此爲false,重複調用則爲ture || !\is_object($this->values[$id])//全部的匿名函數都是object,因此爲false。對應的狀況【3參數】時爲true || isset($this->protected[$this->values[$id]])//未調用protected方法,因此爲false,對應的狀況【4保護參數】時爲true || !\method_exists($this->values[$id], '__invoke')//全部匿名函數存在__invoke方法,因此爲false ) { //綜上,若是是第一次調用,不會執行到這一步,若是是重複調用、參數、protected方法相關的,則會執行 return $this->values[$id]; } //斷定是否是多個實例,對應【2工廠服務】,因爲咱們沒有調用factories方法,因此這一步也不會執行 if (isset($this->factories[$this->values[$id]])) { return $this->values[$id]($this); } //此時$raw就是function ($c) 這個匿名函數 $raw = $this->values[$id]; //從新賦值$this->values['session'],將$this傳入,至關於function ($this),之因此把$this傳遞過來,是由於匿名函數中可能還包含其它的服務, //例如上方的$c['session_storage'],$this傳入後至關於$container['session_storage'],此時會觸發調用offsetGet此方法。 $val = $this->values[$id] = $raw($this); //將原始的匿名函數存入$this->raw中,$this->raw['session']此時有值,重複訪問時在上方斷定時直接返回,至關於單例模式 $this->raw[$id] = $raw; //標記已凍結,已經get後則不容許offsetSet或者extend了 $this->frozen[$id] = true; //返回$this->values['session'] return $val; }
Pimple實現起來比較簡單,主要是經過匿名函數來實現,沒有像yii2容器那樣支持普通類的構造函數自動解析依賴注入關係等,可是對於僅僅是調用各個組件來講也足夠用了。get