Dans Laravel, étant donné que la façade peut fournir une interface « statique » pour le conteneur de services de l'application, par rapport aux méthodes statiques traditionnelles, l'interface « statique » fournie par la façade est équivalente à un représentant statique dans la classe sous-jacente du conteneur de services. , qui peut fournir une syntaxe plus flexible et plus facile à tester, utilisez donc des façades dans Laravel.
L'environnement d'exploitation de cet article : système Windows 10, Laravel version 6, ordinateur Dell G3.
Les façades de Laravel suivent généralement l'idée de base du modèle de façade. La façade de Laravel fournit une interface [statique] pour le conteneur de services de l'application, qui équivaut à un [représentant statique] dans la classe sous-jacente du conteneur de services, qui peut fournir une syntaxe plus flexible, plus facile à tester et plus élégante.
Pour la façade dans Laravel, nous l'utiliserons souvent, comme la mise en cache.
Cache::get('key');
Un autre exemple est la base de données et Redis que nous utilisions souvent auparavant.
DB::connection('mysql2')->table('db_test')->get()->toArray(); Redis::connection('default')->client()->get('test')
Non, la façade est constituée de méthodes statiques. Mais si vous cliquez dessus, vous constaterez qu'il n'y a rien dans cette catégorie de façade !
class Cache extends Facade { protected static function getFacadeAccessor() { return 'cache'; } }
Dans la classe Facade, nous n'avons pas besoin de regarder d'autres fonctions de méthode pour l'instant. Faites simplement défiler vers le bas et vous trouverez une méthode magique, __callStatic().
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); }
__callStatic() signifie que s'il n'y a pas de méthode correspondante définie lors d'un appel statique, elle entrera dans la méthode __callStatic(). Par exemple, la méthode Cache::get() que nous appelons n'est en fait ni la classe de façade Cache actuelle. ni sa classe parent Facade ni sa classe parent ne définissent cette méthode, elle va donc directement à __callStatic(). Ensuite, il récupère l'objet instance de notre façade actuelle via getFacadeRoot(), puis appelle la méthode get() dans l'objet instance.
D'accord, c'est tout. En fait, si un intervieweur vous demande lors de l'entretien comment implémenter le mode façade dans Laravel, vous pouvez affirmer en toute confiance que le noyau est la méthode magique __callStatic(). Alors, d’où vient cet objet d’instance spécifique ? Continuons à regarder vers le bas.
Objet instance
Ensuite, voyons comment obtenir l'objet instance spécifique dans Facade. Ici, nous devons revenir au conteneur de services. Mais regardons d’abord l’entrée.
Dans la méthode __callStatic(), nous verrons qu'une méthode static::getFacadeRoot() est appelée pour obtenir l'objet instance spécifique.
public static function getFacadeRoot() { return static::resolveFacadeInstance(static::getFacadeAccessor()); }
Le contenu de cette méthode est très simple, elle appelle simplement les deux autres méthodes. Notez que getFacadeAccessor() est implémentée dans chacune de nos sous-classes de façade. Par exemple, dans l'exemple, elle est implémentée dans la classe Cache. Il renvoie simplement un alias pour une instance. Rappelez-vous où cet alias a été défini ? Nous l'avons vu dans le conteneur de services, qui est celui défini dans la méthode registerCoreContainerAliases() dans supplier/laravel/framework/src/Illuminate/Foundation/Application.php.
Ensuite, ce que nous examinons principalement est la méthode static::resolveFacadeInstance(). Nous pouvons dire d'après le nom que cela signifie résoudre l'instance de façade. Si cette chose ne renvoie pas d'objet d'instance, elle porte vraiment bien son nom.
protected static function resolveFacadeInstance($name) { if (is_object($name)) { return $name; } if (isset(static::$resolvedInstance[$name])) { return static::$resolvedInstance[$name]; } if (static::$app) { return static::$resolvedInstance[$name] = static::$app[$name]; } }
Le premier jugement est que si un objet est transmis, il sera restitué directement. Le deuxième jugement est que s'il y en a déjà un dans le tableau d'instances actuel, il ne sera pas recréé, ce qui est similaire à l'effet du mode poids mouche. Remarque, tableau de membres statique ! Qu'est-ce que ça veut dire? Statique et globalement partagé, c'est-à-dire qu'une fois votre objet instance créé, il peut être utilisé ailleurs, dans un état singleton complet. Le dernier jugement est que si l'application, c'est-à-dire notre conteneur de services existe, effectuez le fonctionnement du conteneur de services.
Voyons d’abord quand l’attribut app se voit attribuer une valeur. Lorsqu'on parle de fournisseurs de services, il existe un tableau d'attributs de bootstrappers dans le noyau, qui possède un fournisseur RegisterFacades. Évidemment, il s'agit d'un prestataire utilisé pour enregistrer la façade. Dans ce prestataire, nous verrons un code comme celui-ci.
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(); }
Parmi eux, Facade::setFacadeApplication() injecte l'objet Application du conteneur de service dans la variable membre statique app de la classe façade. Notez qu'il est également statique et existe globalement.
Ensuite, nous revenons à la méthode solveFacadeInstance().
protected static function resolveFacadeInstance($name) { // ………… // ………… if (static::$app) { return static::$resolvedInstance[$name] = static::$app[$name]; } }
Que se passe-t-il ici ? Comment puis-je obtenir un objet d'instance via static::$app[$name] ? Ne soyez pas excité, ne soyez pas anxieux, réfléchissez à la façon de faire en sorte qu'un objet effectue de telles opérations sur les tableaux ? Nous l’avons déjà appris !
Il s'agit de l'interface ArrayAccess, et les quelques méthodes qu'elle doit implémenter permettent d'utiliser des objets comme des tableaux.
OK, maintenant que nous connaissons le principe, voyons si c'est le cas et trouvons la classe parent de Application seller/laravel/framework/src/Illuminate/Container/Container.php .
class Container implements ArrayAccess, ContainerContract { // ………… // ………… public function offsetGet($key) { return $this->make($key); } // ………… // ………… }
Ça ne ressemble pas à Baymax ? Je n’ai pas besoin de vous expliquer davantage, n’est-ce pas ? La méthode make() a été expliquée dans le conteneur de service précédent.
D'accord, le reste dépend de vous. Veuillez trouver la classe d'implémentation spécifique de Cache basée sur l'alias dans la méthode registerCoreContainerAliases() dans supplier/laravel/framework/src/Illuminate/Foundation/Application.php, puis analyser son obtention. (), set(), Forget() et d'autres méthodes pour voir comment elles utilisent différentes solutions de stockage de cache en fonction de nos fichiers de configuration.
【Recommandation associée : tutoriel vidéo Laravel】
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!