Laravel - Facade
Laravel - 外观(Facades)
Section titled “Laravel - 外观(Facades)”外观(Facades)为应用服务容器中可用的类提供了一个“静态”接口。Laravel 的外观充当了服务容器中底层类的“静态代理”,提供了简洁、富有表达力的语法,同时比传统的静态方法具有更好的可测试性和灵活性。
所有 Laravel 的外观都定义在 Illuminate\Support\Facades 命名空间下。因此,我们可以很容易地像这样访问一个外观:
use Illuminate\Support\Facades\Cache;
Route::get('/cache', function () { return Cache::get('key');});在 Laravel 文档中,许多示例都会使用外观来演示框架的各种功能。
何时使用外观(Facades)
Section titled “何时使用外观(Facades)”外观有很多好处。它们提供了简洁、易记的语法,让你无需记住那些必须手动注入或配置的长类名就可以使用 Laravel 的功能。此外,由于它们独特地使用了 PHP 的动态方法,它们很容易进行测试。
然而,使用外观时必须小心。外观的主要风险是类范围蔓延(class scope creep)。由于外观非常易于使用且不需要注入,很容易让你的类变得过于庞大,并在一个类中使用许多外观。当使用依赖注入时,通过大型构造函数带来的视觉反馈可以减轻类变得过大的可能性。因此,使用外观时,请特别注意类的规模,以保持其职责范围狭窄。
在构建与 Laravel 交互的第三方包时,通常最好注入 Laravel 的契约(contracts)而不是使用外观。由于包是在 Laravel 本身之外构建的,你将无法访问 Laravel 的外观测试辅助功能。
外观如何工作
Section titled “外观如何工作”在 Laravel 应用中,外观是一个类,它提供了从容器中访问对象的能力。实现此功能的核心在于 Facade 类。Laravel 的外观以及你创建的任何自定义外观都将继承基础的 Illuminate\Support\Facades\Facade 类。
基础 Facade 类利用了 __callStatic() 魔术方法来将对外观的调用延迟到从容器解析出的对象。在下面的示例中,调用了 Laravel 的缓存系统。乍一看这段代码,人们可能会认为静态方法 get 是在 Cache 类上调用的:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;use Illuminate\Support\Facades\Cache;
class UserController extends Controller{ public function index() { $value = Cache::get('key'); // ... }}请注意,在文件顶部我们“导入”了 Cache 外观。这个外观充当了访问底层 Illuminate\Contracts\Cache\Factory 接口实现的代理。我们通过外观进行的任何调用都将传递给 Laravel 缓存服务的底层实例。
如果你查看 Illuminate\Support\Facades\Cache 类,你会发现并没有静态方法 get:
class Cache extends Facade{ protected static function getFacadeAccessor() { return 'cache'; }}相反,Cache 外观继承了基础 Facade 类并定义了 getFacadeAccessor() 方法。该方法的作用是返回服务容器绑定的名称。当用户引用 Cache 外观上的任何静态方法时,Laravel 会从服务容器中解析出 cache 绑定,并对该对象运行请求的方法(在本例中是 get)。
创建自定义外观
Section titled “创建自定义外观”为自己的应用或包创建外观非常简单。你只需要三样东西:
- 一个服务容器绑定。
- 一个外观类。
- 一个外观别名配置(可选,但常用)。
示例:创建一个自定义支付网关外观
Section titled “示例:创建一个自定义支付网关外观”步骤 1:创建服务类。这是将执行实际工作的类。
创建文件 app/Services/PaymentGateway.php:
app/Services/PaymentGateway.php
<?php
namespace App\Services;
class PaymentGateway{ public function processPayment(float $amount) { // 在实际应用中,这里会与支付 API 交互 return "Processing payment of $" . number_format($amount, 2); }}步骤 2:创建一个服务提供者(Service Provider)将你的类绑定到服务容器。
在你的终端中运行 php artisan make:provider PaymentServiceProvider 命令。该命令将在 app/Providers/PaymentServiceProvider.php 中创建一个新的提供者。编辑此文件:
app/Providers/PaymentServiceProvider.php
<?php
namespace App\Providers;
use App\Services\PaymentGateway;use Illuminate\Support\ServiceProvider;
class PaymentServiceProvider extends ServiceProvider{ public function register(): void { $this->app->bind('payment.gateway', function ($app) { return new PaymentGateway(); }); }
public function boot(): void { // }}步骤 3:注册服务提供者。将你的 PaymentServiceProvider 添加到 config/app.php 配置文件中的 providers 数组:
config/app.php (providers 数组片段)
'providers' => ServiceProvider::defaultProviders()->merge([ /* * Application Service Providers... */ App\Providers\AppServiceProvider::class, App\Providers\AuthServiceProvider::class, // App\Providers\BroadcastServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class, App\Providers\PaymentServiceProvider::class, // Add this line])->toArray(),步骤 4:创建外观类。此类应继承 Illuminate\Support\Facades\Facade 并实现 getFacadeAccessor 方法。此方法应返回你在服务提供者中使用的服务容器绑定键 (payment.gateway)。
创建文件 app/Facades/Payment.php:
app/Facades/Payment.php
<?php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Payment extends Facade{ protected static function getFacadeAccessor(): string { return 'payment.gateway'; }}步骤 5:(可选) 添加外观别名。如果你想在不通过完整命名空间导入的情况下使用你的外观,可以将别名添加到 config/app.php 配置文件的 aliases 数组中。
config/app.php (aliases 数组片段)
'aliases' => Facade::defaultAliases()->merge([ 'Payment' => App\Facades\Payment::class,])->toArray(),步骤 6:使用你的新外观。你现在可以在应用中使用你的外观了,例如在路由或控制器中。
routes/web.php
use App\Facades\Payment; // Or use the alias 'Payment' if configured
Route::get('/pay', function(){ return Payment::processPayment(19.99);});步骤 7:测试它。在浏览器中访问 http://localhost:8000/pay。你应该会看到输出:“Processing payment of $19.99”。
下面是每个外观及其底层类的列表。这是一个有用的工具,可以快速查阅给定外观根的 API 文档。如果适用,还包括了服务容器绑定键。
| 外观(Facade) | 类(Class) | 服务容器绑定(Service Container Binding) |
|---|---|---|
| Facade | Class | Service Container Binding |
| App | Illuminate\Foundation\Application | app |
| Artisan | Illuminate\Contracts\Console\Kernel | artisan |
| Auth | Illuminate\Auth\AuthManager | auth |
| Auth (Instance) | Illuminate\Contracts\Auth\Guard | |
| Blade | Illuminate\View\Compilers\BladeCompiler | blade.compiler |
| Broadcast | Illuminate\Contracts\Broadcasting\Factory | broadcast |
| Bus | Illuminate\Contracts\Bus\Dispatcher | bus |
| Cache | Illuminate\Cache\CacheManager | cache |
| Cache (Instance) | Illuminate\Contracts\Cache\Repository | |
| Config | Illuminate\Config\Repository | config |
| Cookie | Illuminate\Cookie\CookieJar | cookie |
| Crypt | Illuminate\Encryption\Encrypter | encrypter |
| DB | Illuminate\Database\DatabaseManager | db |
| DB (Instance) | Illuminate\Database\Connection | |
| Event | Illuminate\Events\Dispatcher | events |
| File | Illuminate\Filesystem\Filesystem | files |
| Gate | Illuminate\Contracts\Auth\Access\Gate | gate |
| Hash | Illuminate\Contracts\Hashing\Hasher | hash |
| Http | Illuminate\Support\Facades\Http | http |
| Lang | Illuminate\Translation\Translator | translator |
| Log | Illuminate\Log\LogManager | log |
| Illuminate\Mail\Mailer | mailer | |
| Notification | Illuminate\Notifications\ChannelManager | notification |
| Password | Illuminate\Auth\Passwords\PasswordBrokerManager | auth.password |
| Password (Instance) | Illuminate\Auth\Passwords\PasswordBroker | |
| Queue | Illuminate\Queue\QueueManager | queue |
| Queue (Instance) | Illuminate\Contracts\Queue\Queue | |
| RateLimiter | Illuminate\Cache\RateLimiter | limiter |
| Redirect | Illuminate\Routing\Redirector | redirect |
| Redis | Illuminate\Redis\RedisManager | redis |
| Redis (Instance) | Illuminate\Contracts\Redis\Connection | |
| Request | Illuminate\Http\Request | request |
| Response | Illuminate\Contracts\Routing\ResponseFactory | response |
| Route | Illuminate\Routing\Router | router |
| Schema | Illuminate\Database\Schema\Builder | db.schema |
| Session | Illuminate\Session\SessionManager | session |
| Session (Instance) | Illuminate\Session\Store | |
| Storage | Illuminate\Filesystem\FilesystemManager | filesystem |
| Storage (Instance) | Illuminate\Contracts\Filesystem\Filesystem | |
| URL | Illuminate\Routing\UrlGenerator | url |
| Validator | Illuminate\Validation\Factory | validator |
| Validator (Instance) | Illuminate\Contracts\Validation\Validator | |
| View | Illuminate\View\Factory | view |
| View (Instance) | Illuminate\Contracts\View\View | |
| Vite | Illuminate\Foundation\Vite |
注意:上述列表是代表性的,可能并非涵盖所有或与最新 Laravel 版本完全同步,但它包含了最常用的外观。始终参考官方 Laravel API 文档以获取最新信息。