久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      Pimple運行流程淺析(PHP容器)

      Pimple運行流程淺析(PHP容器)

      需要具備的知識點

      閉包

      閉包和匿名函數(shù)在PHP5.3.0中引入的。

      閉包是指:

      創(chuàng)建時封裝周圍狀態(tài)的函數(shù)。即使閉包所處的環(huán)境不存在了,閉包中封裝的狀態(tài)依然存在。

      理論上,閉包和匿名函數(shù)是不同的概念。但是PHP將其視作相同概念。

      實際上,閉包和匿名函數(shù)是偽裝成函數(shù)的對象。他們是Closure類的實例。

      閉包和字符串、整數(shù)一樣,是一等值類型。

      創(chuàng)建閉包:

      <?php $closure = function ($name) {     return 'Hello ' . $name; }; echo $closure('nesfo');//Hello nesfo var_dump(method_exists($closure, '__invoke'));//true

      我們之所以能調用$closure變量,是因為這個變量的值是一個閉包,而且閉包對象實現(xiàn)了__invoke()魔術方法。只要變量名后有(),PHP就會查找并調用__invoke()方法。

      通常會把PHP閉包當作函數(shù)的回調使用。

      array_map(), preg_replace_callback()方法都會用到回調函數(shù),這是使用閉包的最佳時機!

      舉個例子:

      <?php $numbersPlusOne = array_map(function ($number) {     return $number + 1; }, [1, 2, 3]); print_r($numbersPlusOne);

      得到結果:

      [2, 3, 4]

      在閉包出現(xiàn)之前,只能單獨創(chuàng)建具名函數(shù),然后使用名稱引用那個函數(shù)。這么做,代碼執(zhí)行會稍微慢點,而且把回調的實現(xiàn)和使用場景隔離了。

      <?php function incrementNum ($number) {     return $number + 1; } $numbersPlusOne = array_map('incrementNum', [1, 2, 3]); print_r($numbersPlusOne);

      SPL

      ArrayAccess

      實現(xiàn)ArrayAccess接口,可以使得object像array那樣操作。ArrayAccess接口包含四個必須實現(xiàn)的方法:

      interface ArrayAccess {     //檢查一個偏移位置是否存在      public mixed offsetExists ( mixed $offset  );          //獲取一個偏移位置的值      public mixed offsetGet( mixed $offset  );          //設置一個偏移位置的值      public mixed offsetSet ( mixed $offset  );          //復位一個偏移位置的值      public mixed offsetUnset  ( mixed $offset  ); }

      SplObjectStorage

      SplObjectStorage類實現(xiàn)了以對象為鍵的映射(map)或對象的集合(如果忽略作為鍵的對象所對應的數(shù)據(jù))這種數(shù)據(jù)結構。這個類的實例很像一個數(shù)組,但是它所存放的對象都是唯一。該類的另一個特點是,可以直接從中刪除指定的對象,而不需要遍歷或搜索整個集合。

      ::class語法

      因為 ::class 表示是字符串。用 ::class 的好處在于 IDE 里面可以直接改名一個 class,然后 IDE 自動處理相關引用。

      同時,PHP 執(zhí)行相關代碼時,是不會先加載相關 class 的。

      同理,代碼自動化檢查 inspect 也可以正確識別 class。

      Pimple容器流程淺析

      Pimpl是php社區(qū)中比較流行的容器。代碼不是很多,詳見

      https://github.com/silexphp/Pimple/blob/master/src/Pimple/Container.php 。

      我們的應用可以基于Pimple開發(fā):

      namespace EasyWeChatFoundation; use PimpleContainer; class Application extends Container {     /**      * Service Providers.      *      * @var array      */     protected $providers = [         ServiceProvidersServerServiceProvider::class,         ServiceProvidersUserServiceProvider::class     ];     /**      * Application constructor.      *      * @param array $config      */     public function __construct($config)     {         parent::__construct();         $this['config'] = function () use ($config) {             return new Config($config);         };         if ($this['config']['debug']) {             error_reporting(E_ALL);         }         $this->registerProviders();     }     /**      * Add a provider.      *      * @param string $provider      *      * @return Application      */     public function addProvider($provider)     {         array_push($this->providers, $provider);         return $this;     }     /**      * Set providers.      *      * @param array $providers      */     public function setProviders(array $providers)     {         $this->providers = [];         foreach ($providers as $provider) {             $this->addProvider($provider);         }     }     /**      * Return all providers.      *      * @return array      */     public function getProviders()     {         return $this->providers;     }     /**      * Magic get access.      *      * @param string $id      *      * @return mixed      */     public function __get($id)     {         return $this->offsetGet($id);     }     /**      * Magic set access.      *      * @param string $id      * @param mixed  $value      */     public function __set($id, $value)     {         $this->offsetSet($id, $value);     } }

      如何使用我們的應用:

      $app = new Application([]); $user = $app->user;

      之后我們就可以使用$user對象的方法了。我們發(fā)現(xiàn)其實并沒有$this->user這個屬性,但是可以直接使用。主要是這兩個方法起的作用:

      public function offsetSet($id, $value){} public function offsetGet($id){}

      下面我們將解釋在執(zhí)行這兩句代碼,Pimple做了什么。但在解釋這個之前,我們先看看容器的一些核心概念。

      服務提供者

      服務提供者是連接容器與具體功能實現(xiàn)類的橋梁。服務提供者需要實現(xiàn)接口ServiceProviderInterface:

      namespace Pimple; /**  * Pimple service provider interface.  *  * @author  Fabien Potencier  * @author  Dominik Zogg  */ interface ServiceProviderInterface {     /**      * Registers services on the given container.      *      * This method should only be used to configure services and parameters.      * It should not get services.      *      * @param Container $pimple A container instance      */     public function register(Container $pimple); }

      所有服務提供者必須實現(xiàn)接口register方法。

      我們的應用里默認有2個服務提供者:

      protected $providers = [     ServiceProvidersServerServiceProvider::class,     ServiceProvidersUserServiceProvider::class ];

      UserServiceProvider為例,我們看其代碼實現(xiàn):

      namespace EasyWeChatFoundationServiceProviders; use EasyWeChatUserUser; use PimpleContainer; use PimpleServiceProviderInterface; /**  * Class UserServiceProvider.  */ class UserServiceProvider implements ServiceProviderInterface {     /**      * Registers services on the given container.      *      * This method should only be used to configure services and parameters.      * It should not get services.      *      * @param Container $pimple A container instance      */     public function register(Container $pimple)     {         $pimple['user'] = function ($pimple) {             return new User($pimple['access_token']);         };     } }

      我們看到,該服務提供者的注冊方法會給容器增加屬性user,但是返回的不是對象,而是一個閉包。這個后面我再做講解。

      服務注冊

      我們在Application里構造函數(shù)里使用$this->registerProviders();對所有服務提供者進行了注冊:

      private function registerProviders() {     foreach ($this->providers as $provider) {         $this->register(new $provider());     } }

      仔細看,我們發(fā)現(xiàn)這里實例化了服務提供者,并調用了容器Pimple的register方法:

      public function register(ServiceProviderInterface $provider, array $values = array()) {     $provider->register($this);     foreach ($values as $key => $value) {         $this[$key] = $value;     }     return $this; }

      而這里調用了服務提供者的register方法,也就是我們在上一節(jié)中提到的:注冊方法給容器增加了屬性user,但返回的不是對象,而是一個閉包。

      當我們給容器Pimple添加屬性user的同時,會調用offsetSet($id, $value)方法:給容器Pimple的屬性values、keys分別賦值:

      $this->values[$id] = $value; $this->keys[$id] = true;

      到這里,我們還沒有實例化真正提供實際功能的類EasyWeChatUserUsr。但已經(jīng)完成了服務提供者的注冊工作。

      當我們運行到這里:

      $user = $app->user;

      會調用offsetGet($id)并進行實例化真正的類:

      $raw = $this->values[$id]; $val = $this->values[$id] = $raw($this); $this->raw[$id] = $raw; $this->frozen[$id] = true; return $val;

      $raw獲取的是閉包:

      $pimple['user'] = function ($pimple) {     return new User($pimple['access_token']); };

      $raw($this)返回的是實例化的對象User。也就是說只有實際調用才會去實例化具體的類。后面我們就可以通過$this['user']或者$this->user調用User類里的方法了。

      當然,Pimple里還有很多特性值得我們?nèi)ド钊胙芯?,這里不做過多講解。

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號