久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放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. 站長(zhǎng)資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

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

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

      需要具備的知識(shí)點(diǎn)

      閉包

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

      閉包是指:

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

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

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

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

      創(chuàng)建閉包:

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

      我們之所以能調(diào)用$closure變量,是因?yàn)檫@個(gè)變量的值是一個(gè)閉包,而且閉包對(duì)象實(shí)現(xiàn)了__invoke()魔術(shù)方法。只要變量名后有(),PHP就會(huì)查找并調(diào)用__invoke()方法。

      通常會(huì)把PHP閉包當(dāng)作函數(shù)的回調(diào)使用。

      array_map(), preg_replace_callback()方法都會(huì)用到回調(diào)函數(shù),這是使用閉包的最佳時(shí)機(jī)!

      舉個(gè)例子:

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

      得到結(jié)果:

      [2, 3, 4]

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

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

      SPL

      ArrayAccess

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

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

      SplObjectStorage

      SplObjectStorage類實(shí)現(xiàn)了以對(duì)象為鍵的映射(map)或?qū)ο蟮募希ㄈ绻雎宰鳛殒I的對(duì)象所對(duì)應(yīng)的數(shù)據(jù))這種數(shù)據(jù)結(jié)構(gòu)。這個(gè)類的實(shí)例很像一個(gè)數(shù)組,但是它所存放的對(duì)象都是唯一。該類的另一個(gè)特點(diǎn)是,可以直接從中刪除指定的對(duì)象,而不需要遍歷或搜索整個(gè)集合。

      ::class語(yǔ)法

      因?yàn)?::class 表示是字符串。用 ::class 的好處在于 IDE 里面可以直接改名一個(gè) class,然后 IDE 自動(dòng)處理相關(guān)引用。

      同時(shí),PHP 執(zhí)行相關(guān)代碼時(shí),是不會(huì)先加載相關(guān) class 的。

      同理,代碼自動(dòng)化檢查 inspect 也可以正確識(shí)別 class。

      Pimple容器流程淺析

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

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

      我們的應(yīng)用可以基于Pimple開(kāi)發(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);     } }

      如何使用我們的應(yīng)用:

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

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

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

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

      服務(wù)提供者

      服務(wù)提供者是連接容器與具體功能實(shí)現(xiàn)類的橋梁。服務(wù)提供者需要實(shí)現(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); }

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

      我們的應(yīng)用里默認(rèn)有2個(gè)服務(wù)提供者:

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

      UserServiceProvider為例,我們看其代碼實(shí)現(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']);         };     } }

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

      服務(wù)注冊(cè)

      我們?cè)?code>Application里構(gòu)造函數(shù)里使用$this->registerProviders();對(duì)所有服務(wù)提供者進(jìn)行了注冊(cè):

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

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

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

      而這里調(diào)用了服務(wù)提供者的register方法,也就是我們?cè)谏弦还?jié)中提到的:注冊(cè)方法給容器增加了屬性user,但返回的不是對(duì)象,而是一個(gè)閉包。

      當(dāng)我們給容器Pimple添加屬性u(píng)ser的同時(shí),會(huì)調(diào)用offsetSet($id, $value)方法:給容器Pimple的屬性values、keys分別賦值:

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

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

      當(dāng)我們運(yùn)行到這里:

      $user = $app->user;

      會(huì)調(diào)用offsetGet($id)并進(jìn)行實(shí)例化真正的類:

      $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)返回的是實(shí)例化的對(duì)象User。也就是說(shuō)只有實(shí)際調(diào)用才會(huì)去實(shí)例化具體的類。后面我們就可以通過(guò)$this['user']或者$this->user調(diào)用User類里的方法了。

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

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