piggly / php-hooks
控制当特定TAG被调用时将执行的钩子。
Requires
- php: ^7.1
Requires (Dev)
- phpunit/phpunit: ^6.4
This package is auto-updated.
Last update: 2024-08-29 05:37:24 UTC
README
要阅读此文件的葡萄牙语版本,请点击此处
此库受到Wordpress核心中可用的函数
do_action和apply_filter的启发。
钩子是在特定、预定义的位置运行某些代码的方式。此功能的主要优点是钩子可以累积在请求时才执行的一组函数。
与Wordpress建议相反,此库中有三种类型的钩子:过滤器、动作和调度器。所有这些都在标签上注册了回调,包括或不包括参数。然后,该标签可以执行。
如果您喜欢这个库并想支持这项工作,请随意向BTC钱包
3DNssbspq7dURaVQH6yBoYwW3PhsNs8dnK捐赠任何金额 ❤。
安装
可以使用Composer通过以下命令安装此库:composer require piggly/php-hooks;
注册回调
只要钩子标签没有被触发,就可以添加和/或删除注册到该标签的回调。对于每个注册的回调,都可以创建一个由以下内容组成的标签:标签名称、函数名称、必需参数和执行优先级。
标签可以通过两种方式形成:使用Syntax::create()函数或使用以下标签语法编写字符串。
标签的语法由以下组成
{tagname}:(必需)标签名称;.{function_name}:函数名称;?{args}:要接收的参数数量,默认总是为1;::{priority}:执行优先级,默认总是为10;
给回调起的名字总是需要唯一的。如果函数名称已存在于标签中,它将引发
NameAlreadyExistsException。
标签语法正则表达式为/^(?:(?P。如果标签语法错误,将引发InvalidSyntaxException。
例如
- 要注册一个具有标签
calculate和优先级1的回调,标签语法将是:calculate::1; - 要注册一个具有标签
calculate、名称pow和接收两个参数的回调,标签语法将是:calculate.pow?2;
下面是另一个示例
// Register in tag calculate $tag = 'calculate'; // Register in tag calculate ready to recieve two args $tag = 'calculate?2'; // Register in tag calculate with priority 1 $tag = 'calculate::1'; // Register in tag calculate ready to recieve two args and priority 1 $tag = 'calculate?2::1'; // Register in tag calculate with name sum $tag = 'calculate.sum'; // Register in tag calculate with name sum ready to recieve two args $tag = 'calculate.pow?2'; // Register in tag calculate with name sum and priority 1 $tag = 'calculate.sum::1'; // Register in tag calculate with name sum, ready to recieve two args and priority 1 $tag = 'calculate.pow?2::1';
回调
除了需要标签外,任何注册的函数还需要一个回调。可以通过Hook::filter()、Hook::action()和Hook::dispatch()方法接收的回调有
Closure:闭包对象类型Hook::filter( $tagSyntax, function ( $number ) { return $number + 15; } );Function:一个指向函数名称的stringHook::filter( $tagSyntax, 'sum' );Static Object:具有静态函数的class,指向类名和静态方法Hook::filter( $tagSyntax, StaticClass::class, 'methodToCall' );Object:一个对象的instance,指向要调用的对象方法Hook::filter( $tagSyntax, $instance, 'methodToCall' );
附加参数
在引用了 callback 之后,最后几个参数将始终是该函数附加的附加参数。例如,Hook::dispatch( $tagSyntax, 'sum', 1 ); 将有一个附加参数为 1。附加参数仅在 Hook::dispatch() 方法中使用。
以下详细了解
Hook::filter()、Hook::action()和Hook::dispatch()。
过滤器 x 动作 x 分发器
这三种类型的钩子的主要区别是
- 过滤器在执行点接收信息,以某种方式修改它并返回它。换句话说:修改某些内容并返回以供下一个过滤器使用,依此类推;
一个过滤器的例子是过滤器
Hook::apply('comment', $comment),它通过删除非法单词、删除链接等来过滤评论。
- 动作在执行点接收信息,对其进行操作并返回空值。换句话说:执行某些操作,然后以开始、中间和结束的方式结束你的代码。
一个动作的例子是创建新票据时的通知
Hook::run('new_ticket', $ticket)。该动作将接收$ticket并相应地发送通知。
- 分发器类似于动作,但它不是在执行点接收信息,而是在注册点接收信息。换句话说:它执行与执行点无关的操作,但会干扰它。
一个分发器的例子是在 HTML 标签中包含 CSS 文件
Hook::run('head')。在这里,分发器将在注册时接收 CSS$name文件,即Hook::dispatch('head', 'importCss', 'home.css')时。
Hook::filter() 过滤器
过滤器 使钩子能够在执行过程中操纵数据。过滤器函数将接收一个变量,修改它并返回它。注册在过滤器中的函数必须独立工作,并且永远不应该有副作用。过滤器始终期望从它们那里返回某些内容。
要将新回调注册到过滤器,应使用以下参数调用 Hook::filter() 方法
$tagSyntax:函数将注册的标签语法;$callback, ?$method:要执行的回调。
要应用过滤器,应使用以下参数调用 Hook::apply() 方法
$tag:将要执行的标签名称;$value:要过滤的初始值;...$params:要过滤的附加参数(Hook::filter()需要能够在标签语法中接收这些参数,以?{args}的形式,默认情况下始终为1);
此外,还有两种 Hook::apply() 方法的变体
Hook::applyByName()仅执行特定标签的一个函数;Hook::applyOnce()仅执行标签一次,之后,它将无法再使用;
还可以使用 Hook::removeFilter() 方法在执行之前删除过滤器。
提示:当过滤器标签在应用程序生命周期中仅使用一次时,请使用
Hook::applyOnce()方法,它将在运行时释放内存空间。
以下是一个使用过滤器的实际示例
function fsum ( $number ) { return $number+15; } function fsub ( $number ) { return $number - 10; } function fmul ( $number ) { return $number * 3; } function fdiv ( $number ) { return $number / 2; } function fpow ( $number, $exp ) { return is_numeric($exp) ? pow($number, $exp) : $number; } Hook::filter('calculate.sum', 'fsum'); Hook::filter('calculate.sub', 'fsub'); Hook::filter('calculate.mul', 'fmul'); Hook::filter('calculate.div', 'fdiv'); // -> Apply => Expects (((10+15)-10)*3)/2 = 22.5 $number = Hook::apply('calculate', 10); echo sprintf("Number: %s\n", $number);
完整示例可在 此处 查看。
Hook::action() 动作
动作 允许您修改应用程序的行为。动作的函数可以写入一些输出,将数据插入数据库,发送通知等。注册在动作中的函数必须始终执行某种类型的任务,因此不会发生任何类型的返回。
要注册一个新回调到动作,应使用以下参数调用方法 Hook::action()
$tagSyntax:函数将注册的标签语法;$callback, ?$method:要执行的回调。
要运行一个动作,应使用以下参数调用方法 Hook::run()
$tag:将要执行的标签名称;...$params:传递给动作的附加参数(Hook::action()需要能够以?{args}语法接收这些参数,默认情况下总是1);
此外,还有两种 Hook::run() 方法变体,它们是:
Hook::runByName()只执行标签的特定功能;Hook::runOnce()只执行一次标签,之后将无法再使用;
还可以使用方法 Hook::removeAction() 在执行前删除动作。
提示:当动作标签在应用程序的生命周期中只使用一次时,请使用
Hook::runOnce()方法,它将在运行时释放内存空间。
以下是一个使用动作的实际示例
function line () { echo "I am line 02\n"; } function message ( $message ) { echo sprintf("Message: %s\n", $message); } Hook::action('sentences.line', 'line'); Hook::action('sentences.message', 'message'); Hook::run('sentences', 'Peace and Love');
完整示例请访问 这里。
分发器 Hook::dispatch()
分发器 具有与动作相同的行为。它们执行没有返回值的代码片段,并通过 Hook::dispatch() 方法注册。然而,它们接收附加参数的方式与动作不同。
假设您的应用程序中有一个 head 钩子,该钩子会在应用程序的 <head> 标签中添加 HTML 标签。
<html> <head> <?php Hook::run('head'); ?> </head> <body> </body> </html>
假设您有一个 Controller,它包含 home()、services() 和 about() 方法(每个页面一个),以及 home.css、services.css 和 about.css 文件。要将这些文件包含在 head 中,需要为每个动作创建一个回调。请参阅
class Controller { // ... public function home() { Hook::action('head', $this, 'homeAction'); // ... } public function services() { Hook::action('head', $this, 'servicesAction'); // ... } public function about() { Hook::action('head', $this, 'aboutAction'); // ... } public function homeAction () { /** Add css file... **/ } public function servicesAction () { /** Add css file... **/ } public function aboutAction () { /** Add css file... **/ } // ... }
这不是很无聊吗?这是因为方法 Hook::run('head') 不会为动作传递参数,并且动作不会接收参数。这是因为我们需要一个回调来处理每个动作。此外,无法在执行点 Hook::run('head') 将 home()、services() 和 about() 所需的参数传递给它们。
分发器就是为了解决这个问题而创建的。在这种情况下,假设我们有一个 importCss($name) 函数。该函数使用 $name 作为 CSS 文件名,在页面中生成 <link> 标签。现在,我们只需要将此函数的分发器与参数 $name 注册。请参阅
class Controller { // ... public function home() { Hook::dispatch('head', 'importCss', 'home.css'); // ... } public function services() { Hook::dispatch('head', 'importCss', 'services.css'); // ... } public function about() { Hook::dispatch('head', 'importCss', 'about.css'); // ... } // ... }
如您所见,我们简化了代码,并且使用了更高效的钩子。使用触发器,我们可以更智能地将函数包含在代码中,而无需依赖与创建的动作等效的函数(因为动作不允许在 Hook::run() 执行点之外传递附加参数)。
非常重要的一点是要理解,钩子 Hook::run('new_ticket', $ticket) 会发送 $ticket 参数,并且该参数将以 Hook::action('new_ticket.notification', 'notification'); 的形式传递给任何动作,但它不会通过 Hook::dispatch('new_ticket.notification', 'notification', $ticket); 传递,后者需要在注册时包含 $ticket。
当需要继承
Hook::run()执行参数时,必须使用动作;而当我们想在钩子内包含具有自己参数的函数时,必须使用分发器。
还可以使用方法 Hook::removeDispatcher() 在执行前删除分发器。
以下是一个使用分发器的实际示例
function name ( $message ) { echo sprintf("Your name: %s\n", $message); } function prog ( $message ) { echo sprintf("Progamming Language: %s\n", $message); } Hook::dispatch('sentences.name::1', 'name', 'Alpha'); Hook::dispatch('sentences.prog::1', 'prog', 'JS'); Hook::run('sentences', 'Peace and Love');
完整示例请访问 这里。
变更日志
请查看CHANGELOG文件,了解所有代码更改的信息。
代码测试
此库使用PHPUnit。我们对本应用程序的所有主要类进行了测试。
vendor/bin/phpunit
贡献
在提交贡献前,请参阅CONTRIBUTING文件获取信息。
安全
如果您发现与安全相关的问题,请发送电子邮件至dev@piggly.com.br,而不是使用GitHub的问题跟踪器。
致谢
支持项目
Piggly Studio是一家位于巴西里约热内卢的代理机构。如果您喜欢这个库并希望支持这项工作,请自由地捐赠任意金额至BTC钱包3DNssbspq7dURaVQH6yBoYwW3PhsNs8dnK ❤。
许可证
MIT许可证(MIT)。请参阅LICENSE。