boxuk / wp-hook-attributes
一个mu-plugin,允许在WordPress钩子中使用PHP属性
Requires
- php: ^7.4 || ^8.0 || ^8.1
- cache/array-adapter: ^1.1
- doctrine/annotations: ^1.13
Requires (Dev)
- phpunit/phpunit: ^7 || ^9
- roots/wordpress: ^5.8
- symfony/dotenv: ^5.3 || ^6.0
- wp-phpunit/wp-phpunit: ^5.8
- yoast/phpunit-polyfills: ^1.0
This package is auto-updated.
Last update: 2024-08-29 05:44:26 UTC
README
安装
composer require boxuk/wp-hook-attributes
启用缓存(使用注解时推荐,用于生产)
基本基于数组的缓存已启用,但生产时您可能希望引入更优的适配器。以下是一个使用memcache的示例,但任何PSR-6适配器都是支持的。
composer require cache/memcache-adapter
use Cache\Adapter\Memcache\MemcacheCachePool; use Psr\Cache\CacheItemPoolInterface; if ( wp_get_environment_type() === 'production' ) { add_filter( 'wp_hook_attributes_cache_adapter', function ( CacheItemPoolInterface $cache_adapter ): CacheItemPoolInterface { global $wp_object_cache; if ( $wp_object_cache->get_mc( 'default' ) instanceof \Memcache ) { $client = $wp_object_cache->get_mc( 'default' ); return new MemcacheCachePool( $client ); } return $cache_adapter; } ); }
注意:这仅适用于使用注解的情况,使用PHP8和属性时不需要。
使用
现在您可以使用注解为函数和方法附加属性并将它们附加到钩子。
use BoxUk\WpHookAttributes\Hook\Attributes\Action; use BoxUk\WpHookAttributes\Hook\Attributes\Filter; // Example of using an action hook #[Action('init')] function basic_action(): string { return 'something...'; } // Example of using a filter hook #[Filter('the_content')] function basic_filter(): string { return 'something...'; } // You can also attach a priority and args #[Action('init', priority: 20, args: 4)] function advanced_action( string $arg1, int $arg2, bool $arg3, array $arg4 ): string return 'something...'; }
还没有使用PHP8?您可以使用注解代替
use BoxUk\WpHookAttributes\Hook\Annotations\Action; use BoxUk\WpHookAttributes\Hook\Annotations\Filter; // Example of using an action hook /** * @Action("init") */ function basic_action(): string { return 'something...'; } // Example of using a filter hook /** * @Filter("the_content") */ function basic_filter(): string { return 'something...'; } // You can also attach a priority and args /** * @Action("init", priority="20", args="4") */ function advanced_action( string $arg1, int $arg2, bool $arg3, array $arg4 ): string return 'something...'; }
注意:低于PHP 7.4的版本不支持。
注册命名空间或前缀(强烈推荐)
您可能想要注册一个命名空间或前缀,以确保它只为您的代码查找属性/注解。您可以通过以下钩子完成此操作
如果您使用注解而不这样做,它可能会非常慢
// Namespace add_filter( 'wp_hook_attributes_registered_namespaces', function(): array { return [ 'BoxUk\Mu\Plugins', ]; }); // Prefix add_filter( 'wp_hook_attributes_registered_prefixes', function(): array { return [ 'boxuk_', ]; });
它执行
stripos()
比较,因此您只需放置命名空间/前缀的前部分即可。
注册文件和类
目前仅适用于在init
钩子之前定义的函数和声明的类。为了解决这个问题,您可以使用以下钩子手动注册函数文件或类。但是,这需要在init
之前完成,否则解析器需要手动调用(下面有详细说明)。
add_filter( 'wp_hook_attributes_registered_function_files', function( array $registered_files ): array { return array_merge( $registered_files, [ 'path/to/my/file/with/functions.php' ] ); }); add_filter( 'wp_hook_attributes_registered_classes', function( array $registered_classes ): array { return array_merge( $registered_classes, [ RegistrationService::class, ] ); });
忽略现有的注解名称
有时在 使用注解时可能会出现错误,提示现有的注解尚未导入。这是因为有时您会发现需要忽略的非标准注解或docblock参数。
一些常见的WordPress和相关库默认被忽略,但这不会涵盖所有内容。
您可以使用以下钩子忽略任何您需要的自定义注解
add_filter( 'wp_hook_attributes_annotation_ignores', function( array $existing_ignores ): array { $existing_ignores[] = 'my-custom-annotation'; return $existing_ignores; } );
限制
在init
之前的钩子上的属性需要更多的工作
如果您想使用在init
钩子之前的钩子,例如muplugins_loaded
,您将无法在这些钩子中使用属性而不进行更多努力。因为这些钩子会在调用钩子解析器之前被调用。
/** * @ActionAnnotation("muplugins_loaded") */ #[Action('muplugins_loaded')] function muplugins_loaded_action(): void { echo 'on muplugins_loaded action'; }
假设您有一个在muplugins_loaded
上的钩子,它是一个预初始化钩子。
/** * @ActionAnnotation("muplugins_loaded") */ #[Action('muplugins_loaded')] function muplugins_loaded_action(): void { echo 'on muplugins_loaded action'; } // Some place earlier than `muplugins_loaded`, maybe a `000-my-project.php` or something within `mu-plugins`. ( new WordPressHookAttributes() )();
muplugins_loaded
钩子会在调用钩子解析器的我们的init
钩子被调用之前被调用。因此,在这些情况下,您需要手动调用钩子解析器,例如
请参阅下一个限制,了解为什么我们默认不提前加载解析器。
muplugins_loaded
registered_taxonomy
registered_post_type
plugins_loaded
sanitize_comment_cookies
setup_theme
unload_textdomain
load_textdomain
after_setup_theme
auth_cookie_malformed
auth_cookie_valid
set_current_user
来源: http://rachievee.com/the-wordpress-hooks-firing-sequence/
函数/方法必须在init
钩子之前注册
属性应该适用于在调用init
钩子之前注册的任何函数/方法。任何作为mu-plugin
或theme
部分注册的函数/方法都应该正常工作,因为这些钩子是在init
之前被调用的。
不会正常工作的是在 init
钩子之后注册的任何函数/方法,例如以下内容不会正常工作,因为 wp_loadded
在 init
之后被调用,因此 my-functions.php
中的函数无法及时注册。
// This will not work. add_action( 'wp_loaded', function() { require_once 'my-functions.php'; });
您可以手动注册文件,但同样,这必须在 init
之前完成,因此要修复上述问题,您可以这样做:
add_action( 'muplugins-loaded', function() { add_filter( 'wp_hook_attributes_registered_function_files', function() { return [ 'my-functions.php'; ]; }); });
类似地,仅仅包含它也会生效。
add_action( 'muplugins-loaded', function() { require_once 'my-functions.php'; });
不支持非静态方法。
如果您有一个依赖于当前对象实例的方法,例如:
class Example { private $foo = 'world'; public function hello(): string { return 'Hello ' . $this->foo; } }
您可以使用 Example
的实例设置一个回调,例如:
$example = new Example(); $callback = [ $example, 'hello' ];
然而,这个库不支持这样做,因为它无法假设如何实例化类。因此,只有静态方法才会工作。这也要求方法被标记为静态,即使它们是隐式静态的。无论如何,这也是一个好的做法,因为如果未显式声明将方法作为静态使用,将会在 PHP 7.4 上引发 PHP 弃用警告,在 PHP 8 上引发致命错误。