当前位置:首页 > CMS教程 > 其它CMS > 列表

PHP Laravel门面的实现原理详解

发布:smiling 来源: PHP粉丝网  添加日期:2023-06-24 18:55:48 浏览: 评论:0 

在Laravel中,门面为应用服务容器中绑定的类提供了一个“静态”接口,使得我们可以不用new这些类出来,就可以直接通过静态接口调用这些类中的方法,本文就来详细聊聊Laravel门面的实现原理,希望对大家有所帮助。

在Laravel中,门面为应用服务容器中绑定的类提供了一个“静态”接口,使得我们可以不用new这些类出来,就可以直接通过静态接口调用这些类中的方法。

下面我们先看看一个门面类是怎么定义的:

  1. <?php 
  2.  
  3. namespace App\Facades; 
  4.  
  5. use Illuminate\Support\Facades\Facade; 
  6.  
  7. class Player extends Facade 
  8.  
  9.     protected static function getFacadeAccessor() { 
  10.         return 'player'
  11.     } 
  12.  

门面类都继承自Illuminate\Support\Facades\Facade父类,这个父类中有一个魔术方法:

  1. /** 
  2.      * Handle dynamic, static calls to the object. 
  3.      * 
  4.      * @param  string  $method 
  5.      * @param  array   $args 
  6.      * @return mixed 
  7.      * 
  8.      * @throws \RuntimeException 
  9.      */ 
  10.     public static function __callStatic($method$args
  11.     { 
  12.         $instance = static::getFacadeRoot(); 
  13.  
  14.         if (! $instance) { 
  15.             throw new RuntimeException('A facade root has not been set.'); 
  16.         } 
  17.  
  18.         return $instance->$method(...$args); 
  19.     } 

当我们静态调用一个不存在的方法时,例如Player::playOneSong(),这个魔术方法就会被调用,它通过getFacadeRoot()方法创建出一个对象,然后在这个对象上真正执行我们的方法。

再看看getFacadeRoot()方法:

  1. /** 
  2.  * Get the root object behind the facade. 
  3.  * 
  4.  * @return mixed 
  5.  */ 
  6. public static function getFacadeRoot() 
  7.     return static::resolveFacadeInstance(static::getFacadeAccessor()); 

这里通过我们自定义门面类中的getFacadeAccessor方法,获取到一个service_id(暂且这么叫吧),然后传给resolveFacadeInstance方法。

再往下看resolveFacadeInstance方法:

  1. /** 
  2.  * Resolve the facade root instance from the container. 
  3.  * 
  4.  * @param  string|object  $name 
  5.  * @return mixed 
  6.  */ 
  7. protected static function resolveFacadeInstance($name
  8.     if (is_object($name)) { 
  9.         return $name
  10.     } 
  11.  
  12.     if (isset(static::$resolvedInstance[$name])) { 
  13.         return static::$resolvedInstance[$name]; 
  14.     } 
  15.  
  16.     return static::$resolvedInstance[$name] = static::$app[$name]; 

通过static::$app[$name]从服务容器中获取 key 为name的对象,服务容器会帮我们实例化出对应的对象(前提是已经绑定好)。

服务容器$app是一个对象,但它实现了ArrayAccess接口,所以可以用这种数组的方式访问。

获取到对象后,放入到static::$resolvedInstance静态变量中,这样下次再获取相同对象时,就不用重复实例化了。

Tags: Laravel门面

分享到: