ホームページ  >  記事  >  バックエンド開発  >  Laravelコア解釈ファサード

Laravelコア解釈ファサード

不言
不言オリジナル
2018-07-06 14:45:451545ブラウズ

この記事では、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配列内<pre class="brush:php;toolbar:false;">&amp;#39;aliases&amp;#39; =&gt; [ &amp;#39;App&amp;#39; =&gt; Illuminate\Support\Facades\App::class, &amp;#39;Artisan&amp;#39; =&gt; Illuminate\Support\Facades\Artisan::class, &amp;#39;Auth&amp;#39; =&gt; Illuminate\Support\Facades\Auth::class, ...... &amp;#39;Route&amp;#39; =&gt; Illuminate\Support\Facades\Route::class, ...... ]</pre>これらのエイリアスが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, &#39;load&#39;], 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::get ( '/uri', 'Controller@action);

、では、Route はルーティング サービスにどのようにプロキシしますか?これには、ファサードでのサービスの暗黙的な解決が含まれます。見てみましょう。ソースRoute クラスのコード: <pre class="brush:php;toolbar:false;">class Route extends Facade { /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return &amp;#39;router&amp;#39;; } }</pre> には単純なメソッドが 1 つだけあり、

get

postdelete などのルーティング メソッドはありません。など、親クラス どちらでもありませんが、クラスに存在しない静的メソッドを呼び出すと、アクセサ (文字列ルーター) セットを通じて PHP の __callStaticstatic メソッド<pre class="brush:php;toolbar:false;">public static function __callStatic($method, $args) { $instance = static::getFacadeRoot(); if (! $instance) { throw new RuntimeException(&amp;#39;A facade root has not been set.&amp;#39;); } return $instance-&gt;$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>がトリガーされることがわかっています。サブクラス Route Facade では、サービス コンテナから対応するサービスを解析します。ルーター サービスは、アプリケーションの初期化時の registerBaseServiceProviders 段階で

\Illuminate\Routing\RoutingServiceProvider

によってサービス コンテナに登録されます (構造を参照) :<pre class="brush:php;toolbar:false;">class RoutingServiceProvider extends ServiceProvider { /** * Register the service provider. * * @return void */ public function register() { $this-&gt;registerRouter(); ...... } /** * Register the router instance. * * @return void */ protected function registerRouter() { $this-&gt;app-&gt;singleton(&amp;#39;router&amp;#39;, function ($app) { return new Router($app[&amp;#39;events&amp;#39;], $app); }); } ...... }</pre>ルーター サービスに対応するクラスは

\Illuminate\Routing\Router

であるため、Route Facade は実際にこのクラスをプロキシし、Route::get は実際には \Illuminate\Routing\Routerオブジェクトの get メソッドを呼び出します<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-&gt;addRoute([&amp;#39;GET&amp;#39;, &amp;#39;HEAD&amp;#39;], $uri, $action); }</pre>2 つの点を追加します:

    サービスの解析時に使用します
  1. static::$app

    は、サービス コンテナを参照する最初の RegisterFacades に設定されます。

  2. static::$app['router']; サービス コンテナからルーター サービスを配列アクセスの形式で解析できる理由は、サービス コンテナが ArrayAccess を実装しているためです。 SPL のインターフェースなどはありません。概念については公式ドキュメントを参照してください。 ArrayAccess
  3. ##概要
Facade の登録と利用プロセスを整理すると、 Facade とサービスプロバイダー (ServiceProvider) が密接に連携していることがわかります。 はい。そのため、将来独自の Laravel カスタムサービスを作成する場合は、コンポーネントの ServiceProvider を通じてサービスをサービスコンテナーに登録するだけでなく、Facade をこれにより、アプリケーションは作成したカスタム サービスに簡単にアクセスできるようになります。

上記がこの記事の全内容です。皆様の学習に少しでもお役に立てれば幸いです。その他の関連コンテンツについては、PHP 中国語 Web サイトをご覧ください。

関連提案:

Laravel ミドルウェアの解釈 (Middleware)

Laravel ルーティングの解釈 (Route)

以上がLaravelコア解釈ファサードの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。