tormjens/eventy

Laravel中的WordPress过滤/操作系统


README

eventy logo


Build Status Coverage Status

Laravel中的动作和过滤器。WordPress风格的。

Eventy(因为没有更好的名字)是一个简单的动作和过滤器(或钩子)系统。

关于

动作是在代码中特定点执行代码片段。动作从不返回任何内容,只是提供了一个钩子选项,以便在不破坏现有代码的情况下将其附加到现有代码。

过滤器用于修改实体。它们总是返回某种类型的值。默认情况下,它们返回第一个参数,你也应该这样做。

了解更多关于过滤器的信息

了解更多关于动作的信息

何时使用Eventy?

Eventy最好用作允许代码扩展性的方式。无论是创建一个包还是应用程序,Eventy都可以带来所需的扩展性。

例如,Eventy可以为基于插件/模块的系统奠定基础。你提供一个“动作”,允许插件注册自己。你可能提供一个“过滤器”,以便插件可以更改核心中的数组内容。你甚至可以提供一个“动作”,以便插件可以修改应用程序的菜单。

Eventy在方法上并不独特。Laravel提供了可宏化的特性,允许你“入侵”类和事件,这样你就可以直接在代码中特定点进行操作。

安装

  1. 使用Composer安装
composer require tormjens/eventy

如果你使用Laravel 5.5或更高版本,你现在可以开始使用这个包了。Eventy被Laravel框架自动发现。

  1. 将服务提供者添加到你的config/app.php中的提供者数组。
    'TorMorten\Eventy\EventServiceProvider',
    'TorMorten\Eventy\EventBladeServiceProvider',
  1. config/app.php中添加外观
    'Eventy' => TorMorten\Eventy\Facades\Events::class,

用法

动作

你可以在代码的任何地方创建一个新的动作,如下所示

use TorMorten\Eventy\Facades\Events as Eventy;

Eventy::action('my.hook', $user);

第一个参数是钩子的名称;你将在稍后使用这个钩子。所有后续参数都作为参数发送给动作。这些可以是任何你想要的内容。例如,你可能想告诉监听器,这被附加到某个特定的模型上。然后,你会将它作为其中一个参数传递。

要监听你的钩子,你需要附加监听器。这些最好添加到你的AppServiceProviderboot()方法中。

例如,如果你想钩入上面的钩子,你可以这样做

Eventy::addAction('my.hook', function($user) {
    if ($user->is_awesome) {
         $this->doSomethingAwesome($user);
    }
}, 20, 1);

再次强调,第一个参数必须是钩子的名称。第二个参数是一个回调。这可以是闭包、指向应用程序容器中类的字符串(MyNamespace\Http\Listener@myHookListener)、数组回调([$object, 'method'])或全局注册的函数function_name。第三个参数是钩子的优先级。数字越低,执行越早。第四个参数指定监听器接受的参数数量。

过滤器

过滤器的工作方式与动作几乎相同,并且结构与动作完全相同。最重要的区别是过滤器总是返回它们的值。

要添加过滤器

$value = Eventy::filter('my.hook', 'awesome');

如果没有监听器附加到此钩子,则过滤器将简单地返回'awesome'

这是向此过滤器添加监听器的方式(仍然在AppServiceProvider中)

Eventy::addFilter('my.hook', function($what) {
    $what = 'not '. $what;
    return $what;
}, 20, 1);

现在过滤器将返回'not awesome'。很酷!

您可以将此与之前的钩子结合使用

Eventy::addAction('my.hook', function($what) {
    $what = Eventy::filter('my.hook', 'awesome');
    echo 'You are '. $what;
});

在 Blade 中使用

既然您已经将 EventBladeServiceProvider 添加到您的配置中,现在有两个指令可用,因此您可以在您的 Blade 模板中使用它。

添加与上面动作示例中相同的动作

@action('my.hook', $user)

添加与上面过滤器示例中相同的过滤器

You are @filter('my.hook', 'awesome')

辅助函数

Eventy 还提供了一些辅助函数,以简化动作和过滤器的使用。

// Add an action
add_action('my.hook', function($user) {
    if ($user->is_awesome) {
         $this->doSomethingAwesome($user);
    }
}, 20, 1);
// Add a filter
add_filter('my.hook', function($what) {
    $what = 'not '. $what;
    return $what;
}, 20, 1);
// Fire an action
do_action('my.hook', $user);
// Fire a filter
apply_filters('my.hook', 'awesome');

使用它来启用可扩展性

以下是一个示例,说明 Eventy 如何在实际应用中使用,其中包含插件的概念。

插件 A 有一个类,用于构建查询以获取所有已发布的文章

class PostsQueryBuilder
{
    public function query()
    {
        return Post::where('published_at', '>', now());
    }
}

使用 Eventy,我可以为其他插件提供一个钩子

use TorMorten\Eventy\Facades\Events as Eventy;
class PostsQueryBuilder
{
    public function query()
    {
        $query = resolve(Post::where('published_at', '>', now());
        return Eventy::filter('posts-query-builder:query', $query);
    }
}

然后,插件 B 出现了,它需要修改该查询以仅包括标题中包含单词 foo 的文章。

在插件 B 的服务提供商(最好在启动方法中,因为这将始终在 Eventy 可用之后触发)中,我们将为该事件添加一个监听器。

use TorMorten\Eventy\Facades\Events as Eventy;

class PluginBServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Eventy::addFilter('posts-query-builder:query', function($query) {
            return $query->where('title', 'like', '%foo%');
        });
    }
}

以下是一个示例,说明如何将动作添加到 blade 模板中,以便插件可以条件性地加载,从而扩展性,抽象模板视图中的控制器依赖。

@foreach ($posts as $post)
    ...
    <p>{{ $post->body }}</p>
    ...
    @action('blade-posts-loop-post-footer', $post)
@endforeach

这允许您的插件/控制器钩入每个博客文章的页脚。

在这个例子中,添加了一个分享链接。

use TorMorten\Eventy\Facades\Events as Eventy;
class SharePostsController
{
    public function boot()
    {
        Eventy::addAction('blade-posts-loop-post-footer', function($post) {
            echo '<a href="twitter.com?share='.$post->url.'">Twitter</a>';
            printf('<a href="https://xyz.com?share='.$post->url.'">XYZbook</a>');
        });
    }
}

在这个例子中,添加了一个评论计数。

use TorMorten\Eventy\Facades\Events as Eventy;
class CommentsPostsController
{
    public function boot()
    {
        Eventy::addAction('blade-posts-loop-post-footer', function($post) {
            echo 'Comments: ' . count($post->comments);
        });
    }
}

致谢