Maison  >  Article  >  développement back-end  >  Façades d'interprétation de Laravel Core

Façades d'interprétation de Laravel Core

不言
不言original
2018-07-06 14:45:451480parcourir

Cet article présente principalement l'interprétation de base des façades dans Laravel, qui a une certaine valeur de référence. Maintenant, je le partage avec tout le monde. Les amis dans le besoin peuvent s'y référer

Que sont les façades

. Les façades sont un composant que nous utilisons très fréquemment dans le développement d'applications Laravel et qui n'est pas appelé de manière appropriée un composant. En fait, il s'agit d'un ensemble d'interfaces de classe statique ou de proxys qui permettent aux développeurs d'accéder simplement à divers services liés au conteneur de services. Les façades sont expliquées dans la documentation Laravel comme suit :

Les façades fournissent une interface "statique" pour les classes disponibles dans le conteneur de services de l'application. Laravel est livré avec de nombreuses façades, et vous les utilisez peut-être sans même le savoir ! En tant que « proxy statique » pour les classes de base dans le conteneur de services, les « façades » Laravel présentent les avantages d'une syntaxe concise et facile à exprimer, tout en conservant une testabilité et une flexibilité plus élevées que les méthodes statiques traditionnelles.

La route que nous utilisons souvent est une façade, qui est un alias de la classe IlluminateSupportFacadesRoute. Cette classe Facade représente le service router enregistré dans le conteneur de services, donc via la classe Route, nous pouvons facilement l'utiliser. divers services fournis dans le service du routeur, et la résolution du service impliquée est complètement implicitement complétée par Laravel, ce qui rend le code d'application beaucoup plus simple dans une certaine mesure. Ci-dessous, nous examinerons brièvement le processus entre l'enregistrement des façades dans le framework Laravel et leur utilisation par l'application. Facades travaille en étroite collaboration avec ServiceProvider, donc si vous comprenez ces processus, il sera utile de développer des composants Laravel personnalisés.

Enregistrer les façades

En parlant d'enregistrement des façades, nous devons revenir à l'étape Bootstrap qui a été mentionnée à plusieurs reprises lors de l'introduction d'autres composants de base. Il y a un démarrage avant que la requête ne passe par le middleware et. routage. Processus de candidature :

//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());
    }
}

Pendant le processus de démarrage de l'application IlluminateFoundationBootstrapRegisterFacades A cette étape, les Façades utilisées dans l'application seront enregistrées.

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();
    }
}

Ici, les alias seront enregistrés pour toutes les façades via les instances de la classe AliasLoader. La correspondance entre les façades et les alias est stockée dans le tableau config/app.php du fichier $aliases

.
'aliases' => [

    'App' => Illuminate\Support\Facades\App::class,
    'Artisan' => Illuminate\Support\Facades\Artisan::class,
    'Auth' => Illuminate\Support\Facades\Auth::class,
    ......
    'Route' => Illuminate\Support\Facades\Route::class,
    ......
]

Regardez comment ces alias sont enregistrés dans 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);
}

Grâce à l'extrait de code ci-dessus, vous pouvez voir qu'AliasLoader enregistre la méthode de chargement en tête de la file d'attente des fonctions SPL __autoload. Jetez un œil au code source de la méthode de chargement :

public function load($alias)
{
    if (isset($this->aliases[$alias])) {
        return class_alias($this->aliases[$alias], $alias);
    }
}

Dans la méthode de chargement, la classe Facade dans la configuration $aliases crée un alias correspondant. Par exemple, lorsque nous utilisons la classe alias <.>, PHP se chargera via AliasLoader. La méthode consiste à créer une classe d'alias Route à partir de la classe IlluminateSupportFacadesRoute::class, donc lorsque nous utilisons l'alias Route dans le programme, nous utilisons en fait la classe Route. `IlluminateSupportFacadesRoute

Service proxy Resolve Facade

Après avoir enregistré Facades dans le framework, nous pouvons utiliser Facade dans l'application. Par exemple, nous utilisons souvent

lors de l'enregistrement d'itinéraires, puis Route::get('/uri', 'Controller@action);Comment. vers le service de routage par proxy ? Cela implique la résolution implicite du service dans la Façade. Jetons un coup d'œil au code source de la classe Route : Route

class Route extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return &#39;router&#39;;
    }
}
Il n'y a qu'une méthode simple, et là. is no

, get, post et les autres méthodes de routage ne sont pas dans la classe parent, mais nous savons que l'appel d'une méthode statique qui n'existe pas dans la classe déclenchera la deleteméthode statique__callStatic de PHP

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];
}
Grâce à l'accesseur (routeur de chaînes) défini dans la sous-classe Route Facade, le service correspondant est analysé à partir du conteneur de services. Le service du routeur est

lors de l'étape registerBaseServiceProviders lors de l'initialisation de l'application (voir la construction. méthode d'application pour plus de détails) La classe correspondant au service de routeur enregistré dans le conteneur de service : IlluminateRoutingRoutingServiceProvider

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);
        });
    }
    ......
}
est

, donc la Route Facade proxy en fait cette classe, et Route::get appelle en fait le Objet IlluminateRoutingRouter Deux points supplémentaires pour la méthode get IlluminateRoutingRouter

/**
 * 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);
}
 :

  1. Le

    utilisé lors de l'analyse du service est défini dans le , dont la référence est le conteneur de service. static::$appRegisterFacades

  2. static::$app['router']; La raison pour laquelle le service de routeur peut être analysé à partir du conteneur de services sous la forme d'un accès au tableau est que le conteneur de services implémente ArrayAccess. interface de SPL. Pour les concepts, vous pouvez lire le document officiel ArrayAccess
  3. Résumé

En triant le processus d'enregistrement et d'utilisation de Facade, nous pouvons voir que Facade et le fournisseur de services (ServiceProvider) travaillent en étroite collaboration, donc si vous écrivez votre propre service personnalisé Laravel à l'avenir, en plus d'enregistrer le service dans le conteneur de services via le ServiceProvider du composant, vous pouvez également fournir une Facade dans le composant afin que l'application puisse accéder facilement au service personnalisé que vous avez écrit.

Ce qui précède représente l'intégralité du contenu de cet article. J'espère qu'il sera utile à l'étude de chacun. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois !

Recommandations associées :

Interprétation du middleware Laravel (Middleware)

Interprétation du routage Laravel (Route)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn