PHP Laravel門面的實現原理詳解
目錄
- 環境
- 原理
環境
Laravel 5.4
原理
在Laravel中,門面為應用服務容器中綁定的類提供了一個“靜態”接口,使得我們可以不用new這些類出來,就可以直接通過靜態接口調用這些類中的方法。
下面我們先看看一個門面類是怎么定義的:
<?php namespace App\Facades; use Illuminate\Support\Facades\Facade; class Player extends Facade { protected static function getFacadeAccessor() { return "player"; } }
門面類都繼承自Illuminate\Support\Facades\Facade父類,這個父類中有一個魔術方法:
/** * Handle dynamic, static calls to the object. * * @param string $method * @param array $args * @return mixed * * @throws \RuntimeException */ public static function __callStatic($method, $args) { $instance = static::getFacadeRoot(); if (! $instance) { throw new RuntimeException("A facade root has not been set."); } return $instance->$method(...$args); }
當我們靜態調用一個不存在的方法時,例如Player::playOneSong(),這個魔術方法就會被調用。它通過getFacadeRoot()方法創建出一個對象,然后在這個對象上真正執行我們的方法。
再看看getFacadeRoot()方法:
/** * Get the root object behind the facade. * * @return mixed */ public static function getFacadeRoot() { return static::resolveFacadeInstance(static::getFacadeAccessor()); }
這里通過我們自定義門面類中的getFacadeAccessor方法,獲取到一個service_id(暫且這么叫吧),然后傳給resolveFacadeInstance方法。
再往下看resolveFacadeInstance方法:
/** * Resolve the facade root instance from the container. * * @param string|object $name * @return mixed */ protected static function resolveFacadeInstance($name) { if (is_object($name)) { return $name; } if (isset(static::$resolvedInstance[$name])) { return static::$resolvedInstance[$name]; } return static::$resolvedInstance[$name] = static::$app[$name]; }
通過static::$app[$name]從服務容器中獲取 key 為name的對象,服務容器會幫我們實例化出對應的對象(前提是已經綁定好)。
服務容器$app是一個對象,但它實現了ArrayAccess接口,所以可以用這種數組的方式訪問。
獲取到對象后,放入到static::$resolvedInstance靜態變量中,這樣下次再獲取相同對象時,就不用重復實例化了。
到此這篇關于PHP Laravel門面的實現原理詳解的文章就介紹到這了,更多相關PHP Laravel門面內容請搜索以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持!
