seothemes / hooks
Requires
- php: ^7.4 || ^8.0
This package is auto-updated.
Last update: 2024-09-14 08:41:59 UTC
README
管理WordPress动作和过滤器钩子的替代语法。
包含两种独立的方法,一种仅使用函数,另一种使用OOP类。该软件包的主要目的是仅使用函数提供此功能,因为已经有很多管理钩子的OOP方法。OOP方法可以作为比较,或在不使用OOP方法的情况下使用。
功能
可移除匿名回调
允许以后删除使用钩子容器添加的匿名函数
// Add hook with anonymous arrow function: add_hook( 'init', 'print_hello_world', function() { print 'Hello world!'; } ); // Remove hook by alias: remove_hook( 'init', 'print_hello_world' );
钩子API语法
允许PHP钩子更紧密地匹配 @wordpress/hooks JS API 语法
addFilter( 'body_class', __NAMESPACE__ . '\\remove_home_body_class', function( array $classes ) : array { return array_diff( $classes, [ 'home' ] ); } );
箭头函数
允许使用可移除的箭头函数作为回调
add_hook( 'init', 'print_hello_world', fn() => print 'Hello world!' ); remove_hook( 'init', 'print_hello_world' );
安装
composer require seothemes/hooks
然后在您的项目中加载composer
require_once __DIR__ . '/vendor/autoload.php';
仅函数的方法可以在 hooks.php
文件中找到。
OOP方法可以在 src
目录中找到。
两者都是独立的,可以单独使用。
所有类和函数都是可插拔的,以避免命名冲突。
示例
添加钩子的常用方法(不使用类时)
function remove_home_body_class( array $classes ): array { return array_diff( $classes, [ 'home' ] ); } add_filter( 'body_class', 'remove_home_body_class', 10, 1 );
在上面的示例中,函数名 remove_home_body_class
必须输入两次。IDE可以提供帮助,但仍然会导致代码重复。此外,使用此方法添加的匿名函数以后无法删除。
使用钩子工具,上面的示例可以重写如下
多行
匹配 @wordpress/hooks JS API 语法
addFilter( 'body_class', 'remove_home_body_class', fn( $classes ) => array_diff( $classes, [ 'home' ] ), 10, 1 );
添加带匿名函数的动作钩子
addAction( 'init', 'my_callback_alias', function() { echo 'Hello World!'; }, 10, 1 );
一行:
add_hook( 'body_class', 'remove_home_body_class', fn( $classes ) => array_diff( $classes, [ 'home' ] ), 10, 1 );
现在函数名已经减少到一,匿名函数可以通过指定的别名以后删除。
工作原理
钩子对象存储在 hook_container
函数中的静态变量 $hooks
中。钩子可以在任何时间添加和从容器中删除,就像常规钩子一样。
add_hook
函数接受与 add_action
和 add_filter
相同的参数,增加“别名”作为第二个参数。
string $hook_name Hook name, e.g `init`
string $alias Function alias. Used for hook removal.
Closure $callback Actual closure to be called.
int $priority Hook priority.
int $accepted_args Accepted number of arguments.
快速设置
使用composer安装到您的自定义插件或主题,或者简单地将 hooks.php
文件中的函数复制粘贴到您的项目中。
composer require seothemes/hooks
添加钩子
安装后,添加以下示例进行测试
namespace Company\Project; require_once __DIR__ . '/vendor/autoload.php'; // Add 'test' class to body. add_hook( 'body_class', 'add_test_class', fn( $classes ) => [ ...$classes, 'test' ] ); var_dump( hook_container() ); // Should return an array of hook objects.
可以使用提供的任何实用函数添加钩子
add_hook( 'body_class', 'remove_home_body_class', fn($classes) => $classes ); addFilter( 'body_class', 'remove_home_body_class', fn($classes) => $classes ); addAction( 'body_class', 'remove_home_body_class', fn($classes) => $classes );
删除钩子
“别名”参数为使用钩子系统注册的匿名函数添加一个ID,允许在以后阶段删除它们。
使用 add_hook
函数添加的钩子只能使用 remove_hook
函数删除。
remove_hook
函数从WordPress注销回调,并从容器中删除钩子。它接受与 remove_action
和 remove_filter
相同的参数
remove_hook( 'body_class', 'remove_home_body_class' );
提供了两个用于删除钩子的包装函数(它们都做同样的事情)
removeFilter( 'body_class', 'remove_home_body_class' ); removeAction( 'body_class', 'remove_home_body_class' );
OOP
此软件包中已包括另一个示例作为OOP的替代方案。安装此软件包时,将自动加载所有类。所有类(和函数)都是可插拔的,以避免命名冲突。
Factory类提供对单个Hooks实例的访问,在您的代码中添加以下行以获取
use SEOThemes\Hooks\Factory; use SEOThemes\Hooks\Hooks; use SEOThemes\Hooks\Container; $hooks = ( new Factory() )->instance( new Hooks( new Container() ) );
要使用 Hooks 类,只需将以下代码添加到您的代码中
use SEOThemes\Hooks\Factory; use SEOThemes\Hooks\Hooks; use SEOThemes\Hooks\Container; $hooks = ( new Factory() )->instance( new Hooks( new Container() ) ); $hooks->add( 'body_class', 'add_body_class', function ( $classes ) { $classes[] = 'test'; return $classes; } ); // To remove the hook uncomment this line. // $hooks->remove( 'body_class', 'add_body_class' );
自动前缀别名
默认情况下,add_hook
函数不添加任何前缀。为了保持代码整洁,我建议创建一个命名空间 const
以缩短别名
namespace Company\Project; const NS = __NAMESPACE__ . '\\'; add_hook( 'body_class', NS . 'remove_test_body_class', function ( $classes ) { return array_diff( $classes, [ 'test' ] ); } );
另一个选项是创建自己的包装函数,该函数将命名空间添加到每个别名前。这也需要一个具有相同别名的自定义移除函数
namespace Company\Project; use Closure; function addNamespacedHook( string $hook_name, string $alias, Closure $callback, int $priority = 10, int $accepted_args = 1 ): bool { return add_hook( $hook_name, __NAMESPACE__ . '\\' . $alias, $callback, $priority, $accepted_args ); } function removeNamespacedHook( string $hook_name, string $alias, int $priority = 10 ): bool { return remove_hook( $hook_name, __NAMESPACE__ . '\\' . $alias, $priority ); }
如果使用面向对象编程,Container 类接受一个可选参数,可以自动将容器内所有别名的前缀设置为给定的字符串
use SEOThemes\Hooks\Factory; use SEOThemes\Hooks\Hooks; use SEOThemes\Hooks\Container; // Inject dependencies. $container = new Container( __NAMESPACE__ . '\\' ); $hooks = new Hooks( $container ); $factory = new Factory(); $instance = $factory->instance( $hooks ); $instance->add('init', 'my_function', fn() => print 'Hello World!' ); $instance->remove('init', 'my_function' ); // Alternative short syntax. ( new Factory() )->instance( new Hooks( new Container( __NAMESPACE__ . '\\' ) ) ) ->add( 'init', 'new_function', fn() => print 'Hello World!' );
容器结构
钩子容器以以下结构存储钩子,以允许有多个钩子和优先级
$hook_container = [ 'hook_name' => [ 'alias' => [ 'priority' => '', // Closure, e.g. fn() => print 'Hello World!'. ], ], ]; // A real example of var_dumping the hook container contents would look something like this: $hook_container = [ 'init' => [ 'print_hello_world' => [ 10 => fn() => print 'Hello World!', 11 => fn() => print 'Hello World, again!', ], 'print_something_else' => [ 10 => fn() => print 'Something else!', ], ], 'body_class' => [ 'add_test_body_class' => [ 10 => fn( $classes ) => [ ...$classes, 'test' ], ], ], ];
测试和贡献
该项目是实验性的,未经进一步测试,不打算用于生产。它旨在作为示例,探索为使用主要是函数式编程的较小项目编写 WordPress 钩子的更灵活和最小化方式。
欢迎并鼓励所有贡献。可能有我还没有想到的更好的实现方式,所以请随意提交拉取请求或打开一个问题。