javanile / eventy
Vtiger中的WordPress过滤器/动作系统
Requires
- php: >=7.0
- opis/closure: ^3.5
- tightenco/collect: ^5.5
Requires (Dev)
- php-coveralls/php-coveralls: ^2.1
- phpunit/phpunit: ^8.0
README
Vtiger中的动作和过滤器。WordPress风格的。
Eventy(由于没有更好的名字)是一个简单的动作和过滤器(如果你喜欢,也可以说是钩子)系统。
关于
动作是你希望在代码的某些特定点执行的代码片段。动作永远不会返回任何内容,只是提供了一个选项,可以在不破坏现有代码的情况下将其钩入。
过滤器是用于修改实体的。它们总是返回某种类型的值。默认情况下,它们返回第一个参数,你也应该这样做。
何时使用Eventy?
Eventy最好用作允许代码扩展的一种方式。无论是创建一个包还是应用程序,Eventy都可以提供所需的扩展性。
例如,Eventy可以为基于插件/模块的系统奠定基础。你可以提供一个“动作”,允许插件注册自己。你可能提供一个“过滤器”,以便插件可以更改核心中的数组内容。你也可以提供一个“动作”,以便插件可以修改应用程序的菜单。
Eventy在方法上并不独特。Laravel提供了允许你“入侵”类和事件的Macroable特性,这样你就可以直接在代码中的特定点进行操作。
安装
- 使用Composer安装
composer require tormjens/eventy
如果你使用的是Laravel 5.5或更高版本,你现在可以开始使用这个包了。Eventy会被Laravel框架自动发现。
- 将服务提供者添加到你的
config/app.php
文件中的providers数组。
'Javanile\Eventy\EventServiceProvider', 'Javanile\Eventy\EventBladeServiceProvider',
- 在
config/app.php
中添加外观
'Eventy' => Javanile\Eventy\Facades\Events::class,
用法
动作
在你的代码的任何地方,你可以创建一个新的动作,如下所示
use Javanile\Eventy\Facades\Events as Eventy; Eventy::action('my.hook', $user);
第一个参数是钩子的名称;你将在稍后使用这个钩子时用到它。所有后续参数都作为参数发送到动作。这些可以是任何你想要的东西。例如,你可能想告诉监听器,这个钩子连接到某个特定的模型。然后,你会将这个作为其中一个参数传递。
要监听你的钩子,请添加监听器。这些最好添加到你的AppServiceProvider
的boot()
方法。
例如,如果你想钩入上面的钩子,你可以这样做
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如何在具有插件概念的实际应用程序中使用。
插件A有一个类,它构建查询以获取所有已发布的帖子
class PostsQueryBuilder { public function query() { return Post::where('published_at', '>', now()); } }
使用Eventy,我可以为其他插件提供可以挂载的过滤器
use Javanile\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 Javanile\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 Javanile\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 Javanile\Eventy\Facades\Events as Eventy; class CommentsPostsController { public function boot() { Eventy::addAction('blade-posts-loop-post-footer', function($post) { echo 'Comments: ' . count($post->comments); }); } }
鸣谢
- 由 Tor Morten Jensen 创建
- 标志由 Caneco 设计