Façades
- Principe de fonctionnement des façades
- Façades en temps réel
- Introduction
- Services de façades pour applications Le conteneur fournit une interface "statique". Laravel est livré avec de nombreuses façades qui donnent accès à la plupart des fonctionnalités. Les façades Laravel sont en fait des « proxys statiques » pour les classes sous-jacentes dans le conteneur de services. Par rapport aux méthodes statiques traditionnelles, elles peuvent fournir une syntaxe plus flexible, plus facile à tester et plus élégante lorsqu'elles sont utilisées. Toutes les façades Laravel sont définies sous l'espace de noms
- . Ainsi, nous pouvons facilement utiliser Facade :
use Illuminate\Support\Facades\Cache; Route::get('/cache', function () { return Cache::get('key'); });
Dans la documentation de Laravel, il existe de nombreux exemples de codes qui utilisent Facades pour démontrer diverses fonctions du framework.
Quand utiliser les façades
Les façades présentent de nombreux avantages. Elles fournissent une syntaxe simple et facile à retenir qui élimine le besoin d'injecter ou de configurer manuellement des noms de classe longs. De plus, ils rendent les tests très faciles grâce à leurs appels uniques aux méthodes statiques PHP.
Cependant, certains endroits nécessitent une attention particulière lors de l’utilisation des façades. Le principal danger lors de l’utilisation de Facades est l’expansion de la portée des classes. Étant donné que les façades sont très simples à utiliser et ne nécessitent pas d'injection, nous pouvons par inadvertance utiliser plusieurs façades dans une seule classe, ce qui rend la classe de plus en plus grande. Cependant, lors de l'utilisation de l'injection de dépendances, plus on utilise de classes, plus le constructeur sera long. Visuellement, on remarquera que cette classe est un peu volumineuse. Par conséquent, lorsque vous utilisez Facades, portez une attention particulière au contrôle de la taille de la classe afin de conserver une portée courte.
Habituellement, les méthodes véritablement statiques sont impossibles à simuler ou à écraser. Cependant, les façades utilisent des méthodes dynamiques pour proxy l'invocation des méthodes objet analysées dans le conteneur de services. Nous pouvons également tester les façades tout comme tester les instances de classe injectées. Par exemple, comme la route suivante :{tip} Lors du développement de packages d'extension tiers qui interagissent avec Laravel, il est préférable d'injecter des contrats Laravel au lieu d'utiliser Facades. Étant donné que le package d'extension est construit en dehors de Laravel, vous ne pouvez pas utiliser Laravel Facades pour tester les fonctions d'assistance. cours injectés. Très utile lors des tests car vous pouvez injecter une simulation ou un stub et affirmer diverses méthodes sur le stub.
use Illuminate\Support\Facades\Cache; Route::get('/cache', function () { return Cache::get('key'); });Nous pouvons écrire le code de test suivant avec les paramètres que nous attendons pour vérifier la méthode
Cache::get
:use Illuminate\Support\Facades\Cache; /** * 一个基础功能的测试。 * * @return void */ public function testBasicExample(){ Cache::shouldReceive('get') ->with('key') ->andReturn('value'); $this->visit('/cache') ->see('value'); }
return View::make('profile');return view('profile');Il n'y a pas de réelle différence entre les façades et les fonctions d'assistance. Lorsque vous utilisez une fonction d'assistance, vous pouvez la tester tout comme la Façade correspondante. Par exemple, la route suivante :
Route::get('/cache', function () { return cache('key');});
Cache::get
方法:use Illuminate\Support\Facades\Cache; /** * 一个基础功能的测试用例。 * * @return void */ public function testBasicExample(){ Cache::shouldReceive('get') ->with('key') ->andReturn('value'); $this->visit('/cache') ->see('value'); }
Facades 相较于辅助函数
除了 Facades,Laravel 还包含各种 『辅助函数』 来实现这些常用功能,比如生成视图、触发事件、任务调度或者发送 HTTP 响应。许多辅助函数都有与之对应的 Facades 。例如,下面这个 Facades 和辅助函数的作用是一样的:
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Cache; class UserController extends Controller{ /** * 显示给定用户的信息。 * * @param int $id * @return Response */ public function showProfile($id) { $user = Cache::get('user:'.$id); return view('profile', ['user' => $user]); } }
Facade 和辅助函数之间没有实际的区别。当你使用辅助函数时,你可以像测试相应的 Facade 那样进行测试。例如,下面的路由:
class Cache extends Facade{ /** * 获取组件的注册名称。 * * @return string */ protected static function getFacadeAccessor() { return 'cache'; } }
在底层实现,辅助函数 cache
实际是调用 Cache
这个 Facade 的 get
est implémentée en bas, et la fonction auxiliaire cache
appelle en fait la méthode get
du Cache
Façade. Par conséquent, même si nous utilisons une fonction d'assistance, nous pouvons toujours écrire le code de test suivant avec les paramètres que nous attendons pour vérifier la méthode :
<?php namespace App; use App\Contracts\Publisher; use Illuminate\Database\Eloquent\Model; class Podcast extends Model{ /** * 发布 Podcast。 * * @param Publisher $publisher * @return void */ public function publish(Publisher $publisher) { $this->update(['publishing' => now()]); $publisher->publish($this); } }
Comment fonctionnent les façades
Dans les applications Laravel, Facade est une classe qui peut accéder aux objets depuis le conteneur. Le composant principal est la classe Facade
. Qu'il s'agisse des propres façades de Laravel ou des façades personnalisées, elles héritent toutes de la classe IlluminateSupportFacadesFacade
. Facade
类。不管是 Laravel 自带的 Facades,还是自定义的 Facades,都继承自 IlluminateSupportFacadesFacade
类。
Facade
基类使用了__callStatic()
魔术方法,直到对象从容器中被解析出来后,才会进行调用。在下面的例子中,调用了 Laravel 的缓存系统。通过浏览这段代码,可以假定在 Cache
类中调用了静态方法 get
:
<?php namespace App; use Facades\App\Contracts\Publisher; use Illuminate\Database\Eloquent\Model; class Podcast extends Model{ /** * 发布 Podcast。 * * @return void */ public function publish() { $this->update(['publishing' => now()]); Publisher::publish($this); } }
注意在上面这段代码中,我们『导入』了 Cache
Facade。这个 Facade 作为访问 IlluminateContractsCacheFactory
接口底层实现的代理。我们使用 Facade 进行的任何调用都将传递给 Laravel 缓存服务的底层实例。
如果我们看一下 IlluminateSupportFacadesCache
这个类,你会发现类中根本没有 get
这个静态方法:
<?php namespace Tests\Feature;use App\Podcast; use Tests\TestCase;use Facades\App\Contracts\Publisher; use Illuminate\Foundation\Testing\RefreshDatabase; class PodcastTest extends TestCase{ use RefreshDatabase; /** * 一个测试演示。 * * @return void */ public function test_podcast_can_be_published() { $podcast = factory(Podcast::class)->create(); Publisher::shouldReceive('publish')->once()->with($podcast); $podcast->publish(); } }
Cache
Facade 继承了 Facade 类,并且定义了 getFacadeAccessor()
方法。这个方法的作用是返回服务容器绑定的名称。当用户调用 Cache
Facade 中的任何静态方法时,Laravel 会从 服务容器 中解析 cache
绑定以及该对象运行所请求的方法(在这个例子中就是 get
方法)。
实时 Facades
使用实时 Facades,你可以将应用程序中的任何类视为 Facade。为了说明这是如何使用的,我们来看看另一种方法。例如,假设我们的 Podcast
模型有一个 publish
方法。然而,为了发布 Podcast,我们需要注入一个 Publisher
实例:
将发布者的实现注入到该方法中,我们可以轻松地测试这种方法,因为我们可以模拟注入的发布者。但是,它要求我们每次调用 publish
方法时都要传递一个发布者实例。使用实时的 Facades,我们可以保持同样的可测试性,而不需要显式地通过 Publisher
实例。要生成实时 Facade
,请在导入类的名称空间中加上 Facades:
当使用实时 Facade 时,发布者实现将通过使用 Facades
Facade
La classe de base utilise la méthode magique __callStatic()
, qui ne sera appelée que lorsque l'objet sera analysé hors du conteneur. Dans l'exemple ci-dessous, le système de mise en cache de Laravel est appelé. En parcourant ce code, on peut supposer que la méthode statique get
est appelée dans la classe Cache
: Si nous regardons la classe IlluminateSupportFacadesCache
, vous constaterez qu'il n'y a pas de méthode statique get
dans la classe : Cache
Façade hérite de la classe Facade et définit la méthode getFacadeAccessor()
. La fonction de cette méthode est de renvoyer le nom de la liaison du conteneur de service. Lorsque l'utilisateur appelle une méthode statique dans la façade Cache
, Laravel résout la liaison cache
du conteneur de service et l'objet exécute la méthode demandée (dans ce cas get
). 🎜🎜🎜🎜Podcast
ait une méthode publish
. Cependant, pour publier un podcast, nous devons injecter une instance Publisher
: 🎜rrreee🎜En injectant l'implémentation de l'éditeur dans la méthode, nous pouvons facilement tester cette approche car nous pouvons nous moquer du publi injecté. Cependant, cela nous oblige à transmettre une instance d'éditeur à chaque fois que nous appelons la méthode publish
. En utilisant Live Facades, nous pouvons maintenir la même testabilité sans passer explicitement une instance Publisher
. Pour générer une Facade
en direct, ajoutez Facades à l'espace de noms de la classe importée : 🎜rrreee🎜 Lors de l'utilisation d'une façade en direct, l'implémentation de l'éditeur apparaîtra en utilisant la partie préfixe Facades
de l'interface ou du nom de classe pour résoudre le problème du conteneur de service. Lors des tests, nous pouvons utiliser la fonction d'assistance de test de façade intégrée de Laravel pour simuler cet appel de méthode : 🎜rrreee🎜🎜🎜🎜🎜🎜Référence de classe Facade
Vous trouverez ci-dessous chaque classe Facade et sa classe sous-jacente correspondante. Il s'agit d'un outil permettant de trouver la documentation API pour une classe Facade donnée. Des informations clés sur les liaisons de conteneurs de services sont également incluses.
Facade | Class | 服务容器绑定 |
---|---|---|
App | IlluminateFoundationApplication | app app |
Artisan | IlluminateContractsConsoleKernel | artisan |
Auth | IlluminateAuthAuthManager | auth |
Auth (Instance) | IlluminateContractsAuthGuard | auth.driver |
Blade | IlluminateViewCompilersBladeCompiler | blade.compiler |
Broadcast | IlluminateContractsBroadcastingFactory | |
Broadcast (Instance) | IlluminateContractsBroadcastingBroadcaster | |
Bus | IlluminateContractsBusDispatcher | |
Cache | IlluminateCacheCacheManager | cache |
Cache (Instance) | IlluminateCacheRepository | cache.store |
Config | IlluminateConfigRepository | config config |
Cookie | IlluminateCookieCookieJar | cookie |
Crypt | IlluminateEncryptionEncrypter | encrypter |
DB | IlluminateDatabaseDatabaseManager | db |
DB (Instance) | IlluminateDatabaseConnection | db.connection |
Event | IlluminateEventsDispatcher | events |
File | IlluminateFilesystemFilesystem | files |
Gate | IlluminateContractsAuthAccessGate | |
Hash | IlluminateContractsHashingHasher | hash |
Lang | IlluminateTranslationTranslator | translator |
Log | IlluminateLogLogManager | log |
IlluminateMailMailer | mailer mailer | |
Notification | IlluminateNotificationsChannelManager | |
Password | IlluminateAuthPasswordsPasswordBrokerManager | auth.password |
Password (Instance) | IlluminateAuthPasswordsPasswordBroker | auth.password.broker |
Queue | IlluminateQueueQueueManager | queue |
Queue (Instance) | IlluminateContractsQueueQueue | queue.connection |
Queue (Base Class) | IlluminateQueueQueue | |
Redirect | IlluminateRoutingRedirector | redirect |
Redis | IlluminateRedisRedisManager | redis |
Redis (Instance) | IlluminateRedisConnectionsConnection | redis.connection |
Request | IlluminateHttpRequest | request |
Response | IlluminateContractsRoutingResponseFactory | |
Réponse (instance) | IlluminateHttpResponse | |
Route | IlluminateRoutingRouter | routeur router |
Schema | IlluminateDatabaseSchemaBuilder | |
Session | IlluminateSessionSessionManager | session |
Session (Instance) | IlluminateSessionStore | session.store |
Storage | IlluminateFilesystemFilesystemManager | filesystem |
Storage (Instance) | IlluminateContractsFilesystemFilesystem | filesystem.disk |
URL | IlluminateRoutingUrlGenerator | url |
Validator | IlluminateValidationFactory | validator |
IlluminateDatabaseSchemaBuilder | ||