この記事では、Laravel におけるファサードのコア解釈を中心に紹介しており、一定の参考価値があるので、皆さんに共有します。必要な友人は参考にしてください。
ファサードは、Laravel アプリケーション開発で頻繁に使用されるコンポーネントです。コンポーネントとは適切には呼ばれませんが、実際には、開発者がサービス コンテナにバインドされたさまざまなサービスに簡単にアクセスできるようにする静的クラス インターフェイスまたはプロキシのセットです。 Laravel ドキュメントのファサードの説明は次のとおりです。
ファサードは、アプリケーションのサービス コンテナで使用できるクラスに「静的」インターフェイスを提供します。 Laravel には多くのファサードが付属しており、知らず知らずのうちにそれらを使用している可能性があります。 Laravel の「ファサード」は、サービスコンテナ内の基本クラスの「静的プロキシ」として、従来の静的メソッドよりも高いテスト容易性と柔軟性を維持しながら、簡潔で表現しやすい構文という利点を備えています。
私たちがよく使うルートは、\Illuminate\Support\Facades\Route
クラスのエイリアスである Facade です。この Facade クラスは、サービス コンテナに登録されている を表します.router
サービスなので、Route クラスを通じて、ルーター サービスで提供されるさまざまなサービスを簡単に使用でき、関連するサービスの解決は Laravel によって完全に暗黙的に完了されるため、アプリケーションはある程度のコードになります。もっとシンプルに。以下では、Facade が Laravel フレームワークに登録されてからアプリケーションで使用されるまでのプロセスを簡単に見ていきます。ファサードは ServiceProvider と密接に連携するため、これらのプロセスを理解していれば、カスタム Laravel コンポーネントを開発するのに役立ちます。
ファサードの登録に関しては、他のコア コンポーネントを導入するときに何度も言及したブートストラップの段階に戻る必要があります。リクエストが通過する前に起動があります。アプリケーション プロセス:
//Class: \Illuminate\Foundation\Http\Kernel protected function sendRequestThroughRouter($request) { $this->app->instance('request', $request); Facade::clearResolvedInstance('request'); $this->bootstrap(); return (new Pipeline($this->app)) ->send($request) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter()); } //引导启动Laravel应用程序 public function bootstrap() { if (! $this->app->hasBeenBootstrapped()) { /**依次执行$bootstrappers中每一个bootstrapper的bootstrap()函数 $bootstrappers = [ 'Illuminate\Foundation\Bootstrap\DetectEnvironment', 'Illuminate\Foundation\Bootstrap\LoadConfiguration', 'Illuminate\Foundation\Bootstrap\ConfigureLogging', 'Illuminate\Foundation\Bootstrap\HandleExceptions', 'Illuminate\Foundation\Bootstrap\RegisterFacades', 'Illuminate\Foundation\Bootstrap\RegisterProviders', 'Illuminate\Foundation\Bootstrap\BootProviders', ];*/ $this->app->bootstrapWith($this->bootstrappers()); } }
アプリケーションの開始プロセス中Illuminate\Foundation\Bootstrap\RegisterFacades
このステージでは、アプリケーションで使用されるファサードを登録します。
class RegisterFacades { /** * Bootstrap the given application. * * @param \Illuminate\Contracts\Foundation\Application $app * @return void */ public function bootstrap(Application $app) { Facade::clearResolvedInstances(); Facade::setFacadeApplication($app); AliasLoader::getInstance(array_merge( $app->make('config')->get('app.aliases', []), $app->make(PackageManifest::class)->aliases() ))->register(); } }
ここでは、AliasLoader
クラスのインスタンスを通じてすべてのファサードのエイリアスが登録されます。ファサードとエイリアスの対応関係は、config/app.php## に保存されます。 ##$aliases
配列内<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">&#39;aliases&#39; => [
&#39;App&#39; => Illuminate\Support\Facades\App::class,
&#39;Artisan&#39; => Illuminate\Support\Facades\Artisan::class,
&#39;Auth&#39; => Illuminate\Support\Facades\Auth::class,
......
&#39;Route&#39; => Illuminate\Support\Facades\Route::class,
......
]</pre><div class="contentsignin">ログイン後にコピー</div></div>
これらのエイリアスがAliasLoaderにどのように登録されているかを確認してください
// class: Illuminate\Foundation\AliasLoader public static function getInstance(array $aliases = []) { if (is_null(static::$instance)) { return static::$instance = new static($aliases); } $aliases = array_merge(static::$instance->getAliases(), $aliases); static::$instance->setAliases($aliases); return static::$instance; } public function register() { if (! $this->registered) { $this->prependToLoaderStack(); $this->registered = true; } } protected function prependToLoaderStack() { // 把AliasLoader::load()放入自动加载函数队列中,并置于队列头部 spl_autoload_register([$this, 'load'], true, true); }
上記のコード スニペットを通して、AliasLoaderがロードを登録していることがわかります。 SPL __autoload 関数へのメソッド キューの先頭。ロード メソッドのソース コードを見てください:
public function load($alias) { if (isset($this->aliases[$alias])) { return class_alias($this->aliases[$alias], $alias); } }
ロード メソッド
$aliases では、構成内の Facade クラスが対応するエイリアスを作成します。たとえば、エイリアスを使用する場合、 class Route
PHP は、AliasLoader のload メソッドを通じて Illuminate\Support\Facades\Route::class
クラスのエイリアス クラス Route
を作成します。そのため、次を使用します。プログラム内のエイリアス Route
実際には、`Illuminate\Support\Facades\Route
クラスが使用されます。 Facade プロキシ サービスの解決
、では、Route
はルーティング サービスにどのようにプロキシしますか?これには、ファサードでのサービスの暗黙的な解決が含まれます。見てみましょう。ソースRoute クラスのコード: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">class Route extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return &#39;router&#39;;
}
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
には単純なメソッドが 1 つだけあり、
、post
、delete
などのルーティング メソッドはありません。など、親クラス どちらでもありませんが、クラスに存在しない静的メソッドを呼び出すと、アクセサ (文字列ルーター) セットを通じて PHP の __callStatic
static メソッド<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">public static function __callStatic($method, $args)
{
$instance = static::getFacadeRoot();
if (! $instance) {
throw new RuntimeException(&#39;A facade root has not been set.&#39;);
}
return $instance->$method(...$args);
}
//获取Facade根对象
public static function getFacadeRoot()
{
return static::resolveFacadeInstance(static::getFacadeAccessor());
}
/**
* 从服务容器里解析出Facade对应的服务
*/
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];
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
がトリガーされることがわかっています。サブクラス Route Facade では、サービス コンテナから対応するサービスを解析します。ルーター サービスは、アプリケーションの初期化時の registerBaseServiceProviders 段階で
によってサービス コンテナに登録されます (構造を参照) :<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">class RoutingServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->registerRouter();
......
}
/**
* Register the router instance.
*
* @return void
*/
protected function registerRouter()
{
$this->app->singleton(&#39;router&#39;, function ($app) {
return new Router($app[&#39;events&#39;], $app);
});
}
......
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
ルーター サービスに対応するクラスは
であるため、Route Facade は実際にこのクラスをプロキシし、Route::get は実際には \Illuminate\Routing\Router
オブジェクトの get メソッドを呼び出します<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">/**
* Register a new GET route with the router.
*
* @param string $uri
* @param \Closure|array|string|null $action
* @return \Illuminate\Routing\Route
*/
public function get($uri, $action = null)
{
return $this->addRoute([&#39;GET&#39;, &#39;HEAD&#39;], $uri, $action);
}</pre><div class="contentsignin">ログイン後にコピー</div></div>2 つの点を追加します:<p></p>
<ol class=" list-paddingleft-2">サービスの解析時に使用します<li> static::$app<p> は、サービス コンテナを参照する最初の <code>RegisterFacades
に設定されます。
Laravel ミドルウェアの解釈 (Middleware)
以上がLaravelコア解釈ファサードの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。