神奇的 Laravel 宏指令(Macro)
可曾有过想要的一项功能在Laravel中,但它又不是真实存在的?让我来给你介绍一下Laravel宏指令。宏指令允许你添加自定义功能到Laravel的内部组件里去。
让我们以一个简单的Request
门面方法为例。
Request::macro('introduce', function ($name) {
echo 'Hello ' . $name . '!';
});
Request::introduce('Caleb'); // outputs "Hello Caleb!"
一个更加实用的Request
宏指令是用于检测当前的TLD(顶级域:.com,.net,.org,.etc…)。
Request::macro('tldIs', function ($tld) {
return Str::is('*.' . $tld, $this->root());
});
Request::tldIs('com') // returns true for app.com
Request::tldIs('dev') // returns false for app.com
你会注意到Laravel自动绑定$this
到Request
的上下文中,而不是在一个已经定义宏的类里。比如:
class AppServiceProvider
{
public function boot()
{
Request::macro('context', function () {
return get_class($this);
}
}
...
Request::context();
// returns 'Illuminate\Http\Request'
// instead of 'App\AppServiceProvider'
让我们看一个更高级的示例。此宏有条件地基于当前TLD在模型上添加一个where
语句。
Builder::macro('whenTldMatches', function($tld, $callback) {
if (Request::tldIs($tld)) {
call_user_func($callback->bindTo($this));
}
return $this;
});
SomeModel::whenTldMatches('org', function () {
$this->where('id', '>', 5);
})->get();
// applies ->where() 在 app.org 上应用,而不在 app.com 上应用
我们应该在哪里定义它们?
服务提供者为为您的应用程序定义宏的好地方。App\Providers\AppServiceProvider
boot()
是I一个很好的注入点,但是它很快就变得臃肿。
下一步是创建一个 App\Providers\MacrosServiceProvider
并注册在 config/app.php
里。 如果某宏与之相关,我可能会创建一个App\Providers\TldAwareServiceProvider
来容纳所有与TLD相关的宏。
哪些组件是 Macroable
?
宏可以再任何具有Macroable
特性的类上定义。下面是一个Macroable
的门面和类的列表
门面
- Cache
- File
- Lang
- Request
- Response
- Route
- URL
Illuminate Classes
- Illuminate\Cache\Repository
- Illuminate\Console\Scheduling\Event
- Illuminate\Database\Eloquent\Builder
- Illuminate\Database\Eloquent\Relation
- Illuminate\Database\Query\Builder
- Illuminate\Filesystem\Filesystem
- Illuminate\Foundation\Testing\TestResponse
- Illuminate\Http\RedirectResponse
- Illuminate\Http\Request
- Illuminate\Http\UploadedFile
- Illuminate\Routing\ResponseFactory
- Illuminate\Routing\Router
- Illuminate\Routing\UrlGenerator
- Illuminate\Support\Arr
- Illuminate\Support\Collection
- Illuminate\Support\Str
- Illuminate\Translation\Translator
- Illuminate\Validation\Rule
动手
如果您发现自己在整个系统中对Laravel组件重复执行逻辑,请考虑使用宏以实现更好的表达和重用。相信我,非常馋。
祝您好运!
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: