PHP預定義介面之 ArrayAccess,php預定arrayaccess
最近這段時間回家過年了,部落格也沒有更新,感覺少學習了好多東西,也錯失了好多的學習機會,就像大家在春節搶紅包時常說的一句話:一不留神錯過了好幾億。廢話少說,這篇部落格給大家說說關於PHP預定義介面中常用到的重量級人物: ArrayAccess。大家也許會問,最基本、最常用的預定義介面有6個呢,為啥非得說這個。從日常的使用方式來看:這個出現的頻率非常高,特別是在架構中,比如Laravel、Slim等都會用到,並且用得非常經典,讓人佩服啊。從技術上說:說實話其他的我用的少啊!只是知道簡單的用法,對他的理解比較淺顯,不敢在這裡誤導大家,哈哈!今天我要寫的內容也不一定都正確,不對之處還請指正。
ArrayAccess
先說 ArrayAccess 吧!ArrayAccess 的作用是使得你的對象可以像數組一樣可以被訪問。應該說 ArrayAccess 在PHP5中才開始有的,PHP5中加入了很多新的特性,當然也使類的重載也加強了,PHP5 中添加了一系列介面,這些介面和實現的 Class 統稱為 SPL。
ArrayAccess 這個介面定義了4個必須要實現的方法:
1 {2 abstract public offsetExists ($offset) //檢查位移位置是否存在3 abstract public offsetGet ($offset) //擷取一個位移位置的值4 abstract public void offsetSet ($offset ,$value) //設定一個位移位置的值5 abstract public void offsetUnset ($offset) //複位一個位移位置的值6 }
所以我們要使用ArrayAccess這個介面,就要實現相應的方法,這幾個方法不是隨便寫的,我們可以看一下 ArrayAccess 的原型:
1 /** 2 * Interface to provide accessing objects as arrays. 3 * @link http://php.net/manual/en/class.arrayaccess.php 4 */ 5 interface ArrayAccess { 6 7 /** 8 * (PHP 5 >= 5.0.0)
9 * Whether a offset exists10 * @link http://php.net/manual/en/arrayaccess.offsetexists.php11 * @param mixed $offset 12 * An offset to check for.13 *
14 * @return boolean true on success or false on failure.15 * 16 * 17 * The return value will be casted to boolean if non-boolean was returned.18 */19 public function offsetExists($offset);20 21 /**22 * (PHP 5 >= 5.0.0)
23 * Offset to retrieve24 * @link http://php.net/manual/en/arrayaccess.offsetget.php25 * @param mixed $offset
26 * The offset to retrieve.27 *
28 * @return mixed Can return all value types.29 */30 public function offsetGet($offset);31 32 /**33 * (PHP 5 >= 5.0.0)
34 * Offset to set35 * @link http://php.net/manual/en/arrayaccess.offsetset.php36 * @param mixed $offset 37 * The offset to assign the value to.38 *
39 * @param mixed $value 40 * The value to set.41 *
42 * @return void43 */44 public function offsetSet($offset, $value);45 46 /**47 * (PHP 5 >= 5.0.0)
48 * Offset to unset49 * @link http://php.net/manual/en/arrayaccess.offsetunset.php50 * @param mixed $offset 51 * The offset to unset.52 *
53 * @return void54 */55 public function offsetUnset($offset);56 }
下面我們可以寫一個例子,非常簡單:
1 php 2 class Test implements ArrayAccess 3 { 4 private $testData; 5 6 public function offsetExists($key) 7 { 8 return isset($this->testData[$key]); 9 }10 11 public function offsetSet($key, $value)12 {13 $this->testData[$key] = $value;14 }15 16 public function offsetGet($key)17 {18 return $this->testData[$key];19 }20 21 public function offsetUnset($key)22 {23 unset($this->testData[$key]);24 }25 }26 27 $obj = new Test();28 29 //自動調用offsetSet方法30 $obj['data'] = 'data';31 32 //自動調用offsetExists33 if(isset($obj['data'])){34 echo 'has setting!';35 }36 //自動調用offsetGet37 var_dump($obj['data']);38 39 //自動調用offsetUnset40 unset($obj['data']);41 var_dump($test['data']);42 43 //輸出:44 //has setting!45 //data 46 //null
好了,下面我們會結合Slim架構來說在實際中的應用,在Slim中使用非常重要,也非常出色的使用了 container,container繼承自Pimple\Container,說到這,就有必要說一下Pimple,pimple是php社區中比較流行的一種ioc容器,pimple中的container類使用了依賴注入的方式來實現實現了程式間的低耦合,可以用composer添加 require "pimple/pimple": "1.*" 添加Pimple到依賴類庫,Pimple還是要多看看的,就一個檔案,在程式整個生命週期中,各種屬性、方法、對象、閉包都可以註冊其中,但pimple只是實現了一個容器的概念,還有好多依賴注入、自動建立、關聯等功能需要看Laravel才能深刻學到。
在Slim中它使用 container 的類實現了將設定檔依次載入,可以像訪問數組一樣訪問他們,包括displayErrorDetails,renderer, logger,httpVersion,responseChunkSize,outputBuffering,determineRouteBeforeAppMiddleware,displayErrorDetails等等,使他們在架構載入的時候首先被載入。使用的時候直接取就可以了,
下面就是這種載入機制:
phpnamespace Slim;use Interop\Container\ContainerInterface;use Interop\Container\Exception\ContainerException;use Pimple\Container as PimpleContainer;use Psr\Http\Message\ResponseInterface;use Psr\Http\Message\ServerRequestInterface;use Slim\Exception\ContainerValueNotFoundException;class Container extends PimpleContainer implements ContainerInterface{ /** * Default settings * * @var array */ private $defaultSettings = [ 'httpVersion' => '1.1', 'responseChunkSize' => 4096, 'outputBuffering' => 'append', 'determineRouteBeforeAppMiddleware' => false, 'displayErrorDetails' => false, ]; /** * Create new container * * @param array $values The parameters or objects. */ public function __construct(array $values = []) { //var_dump($values); exit; parent::__construct($values); $userSettings = isset($values['settings']) ? $values['settings'] : []; $this->registerDefaultServices($userSettings); } private function registerDefaultServices($userSettings) { $defaultSettings = $this->defaultSettings; $this['settings'] = function () use ($userSettings, $defaultSettings) { return new Collection(array_merge($defaultSettings, $userSettings)); }; $defaultProvider = new DefaultServicesProvider(); $defaultProvider->register($this); } . . .}
其中 defaultSettings 為系統預設配置,userSettings為使用者的配置,比如日誌,模板等。
下面這段是offsetGet,巧妙使用索引值來判斷該值是否已經設定過,如果設定過就會直接去取了,沒有設定就會轉到設定的邏輯。
1 public function offsetGet($id) 2 { 3 if (!isset($this->keys[$id])) { 4 throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id)); 5 } 6 7 if ( 8 isset($this->raw[$id]) 9 || !is_object($this->values[$id])10 || isset($this->protected[$this->values[$id]])11 || !method_exists($this->values[$id], '__invoke')12 ) {13 return $this->values[$id];14 }15 16 if (isset($this->factories[$this->values[$id]])) {17 return $this->values[$id]($this);18 }19 20 $raw = $this->values[$id];21 $val = $this->values[$id] = $raw($this);22 $this->raw[$id] = $raw;23 24 $this->frozen[$id] = true;25 26 return $val;27 }
我們再看看 PimpleContainer,如:
我們可以看到其中有個 SplObjectStorage,需要說一下這個,SplObjectStorage是用來儲存一組對象,當你需要唯一標識對象的時候。按照官網的說法 PHP SPL SplObjectStorage類實現了Countable, Iterator, Serializable, ArrayAccess四個介面,可實現統計、迭代、序列化、數組式訪問等功能。所以SplObjectStorage是一個標準的對象容器。
說到這大家對ArrayAccess應該有所瞭解了,如果還不清楚,可以多看看Slim的源碼,上面寫的比較清楚,而且那套源碼及其的簡練,值得我們學習。
部落格會同步更新到我的個人網站,歡迎大家訪問!
轉載請註明出處,後面會持續更新,謝謝大家!
http://www.bkjia.com/PHPjc/1104066.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/1104066.htmlTechArticlePHP預定義介面之 ArrayAccess,php預定arrayaccess 最近這段時間回家過年了,部落格也沒有更新,感覺少學習了好多東西,也錯失了好多的學習機會...