WordPress 中最强大的工具之一是它使用的钩子系统。这是从任何地方修改值的好方法。它为任何 WordPress 网站增加了巨大的灵活性。让我们看一下,如何在 Laravel 中实现这一点
基本概念
基本思想与 WordPress 钩子系统其实是一样的。代码中的某处有一些值,我们希望从外部轻松修改它们,而无需修改任何代码。此外,设置优先级会很好,因为我们可以更好地控制修改
事件与钩子
如果我们可以使用 Laravel 的事件系统来实现这个功能,那就太好了,但这并不理想。因此,我们将实现一个小型钩子存储库,它将根据优先级存储和排序已注册的钩子
挂钩存储库
这个存储库将是一个非常简单的地方来存储我们的钩子并在我们需要时使用它们
class HookRepository
{
/**
* The repository items.
*
* @var \Illuminate\Support\Collection
*/
protected $items;
/**
* Create a new repository instance.
*
* @return void
*/
public function __construct()
{
$this->items = collect();
}
/**
* Dynamically call methods.
*
* @param string $method
* @param array $arguments
* @return mixed
*/
public function __call(string $method, array $arguments)
{
return $this->items->{$method}(...$arguments);
}
/**
* Register a new hook callback.
*
* @param string|array $hook
* @param callable $callback
* @param int $priority
* @return void
*/
public function register($hook, callable $callback, int $priority = 10): void
{
$this->items->push(compact('hook', 'callback', 'priority'));
}
/**
* Apply the callbacks on the given hook and value.
*
* @param string $hook
* @param array $arguments
* @return mixed
*/
public function apply(string $hook, ...$arguments)
{
return $this->items->filter(function ($filter) use ($hook) {
return !! array_filter((array) $filter['hook'], function ($item) use ($hook) {
return Str::is($item, $hook);
});
})->sortBy('priority')->reduce(function ($value, $filter) use ($arguments) {
return call_user_func_array($filter['callback'], [$value] + $arguments);
}, $arguments[0] ?? null);
}
}
所以,我们这里有两个方法,register和apply。所有其他调用将被转发到持有钩子的集合实例
我们可以在服务提供者中注册钩子,例如 :
public function boot()
{
Hook::register('jobs.tags', function ($tags, $job) {
return array_merge($tags, $job->someCondition() ? ['foo'] : ['bar']);
});
}
请注意,使用这种方法,我们也可以使用通配符或数组表示法注册挂钩。
例如:[jobs.tags, posts.tags]或jobs.*
应用挂钩
那么,在哪里应用钩子呢?基本上你想要的任何地方。该解决方案的好处是,您实际上并不需要针对不同地方的复杂价值管理器。您可以使用钩子,传递您想要的任何参数,并返回稍后将使用的修改后的值
public function tags()
{
return Hook::apply('jobs.tags', ['a', 'b'], $this);
}
我们调用apply方法并首先传递钩子和值,然后是回调中可能需要的任何其他参数