{"id":19311078,"url":"https://github.com/boxuk/wp-hook-attributes","last_synced_at":"2026-01-15T03:59:45.009Z","repository":{"id":43399134,"uuid":"392737735","full_name":"boxuk/wp-hook-attributes","owner":"boxuk","description":"A library to allow the use of PHP attributes for WordPress hooks","archived":true,"fork":false,"pushed_at":"2025-01-21T16:28:29.000Z","size":63,"stargazers_count":9,"open_issues_count":1,"forks_count":0,"subscribers_count":9,"default_branch":"main","last_synced_at":"2026-01-14T14:30:32.299Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/boxuk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-08-04T15:23:44.000Z","updated_at":"2025-12-06T18:01:24.000Z","dependencies_parsed_at":"2025-04-22T14:40:10.530Z","dependency_job_id":"0c38101d-4495-49db-b414-636b3b88f0e4","html_url":"https://github.com/boxuk/wp-hook-attributes","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/boxuk/wp-hook-attributes","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxuk%2Fwp-hook-attributes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxuk%2Fwp-hook-attributes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxuk%2Fwp-hook-attributes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxuk%2Fwp-hook-attributes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/boxuk","download_url":"https://codeload.github.com/boxuk/wp-hook-attributes/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxuk%2Fwp-hook-attributes/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28442357,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-15T00:55:22.719Z","status":"online","status_checked_at":"2026-01-15T02:00:08.019Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-10T00:27:35.407Z","updated_at":"2026-01-15T03:59:44.991Z","avatar_url":"https://github.com/boxuk.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WordPress Hook Attributes\n\n\u003e This project is now abandoned. If you're interested in taking it over, get in touch.\n\n## Installation\n\n`composer require boxuk/wp-hook-attributes`\n\n### Enable caching (recommended for production when using annotations)\n\nBasic array based caching is enabled as standard but in production you may wish to bring in a more optimal adapter. Below is an example using memcache, but any [PSR-6](https://www.php-fig.org/psr/psr-6/) adapter is supported.\n\n`composer require cache/memcache-adapter`\n\n```php\nuse Cache\\Adapter\\Memcache\\MemcacheCachePool;\nuse Psr\\Cache\\CacheItemPoolInterface;\n\nif ( wp_get_environment_type() === 'production' ) {\n\tadd_filter(\n\t\t'wp_hook_attributes_cache_adapter',\n\t\tfunction ( CacheItemPoolInterface $cache_adapter ): CacheItemPoolInterface {\n\t\t\tglobal $wp_object_cache;\n\t\t\tif ( $wp_object_cache-\u003eget_mc( 'default' ) instanceof \\Memcache ) {\n\t\t\t\t$client = $wp_object_cache-\u003eget_mc( 'default' );\n\n\t\t\t\treturn new MemcacheCachePool( $client );\n\t\t\t}\n\n\t\t\treturn $cache_adapter;\n\t\t}\n\t);\n}\n```\n\n\u003e Note: This only applies when using annotations, not needed when using PHP8 and attributes.\n\n## Usage\n\nNow you can annotate functions and methods with attributes to attach them to a hook.\n\n```php\nuse BoxUk\\WpHookAttributes\\Hook\\Attributes\\Action;\nuse BoxUk\\WpHookAttributes\\Hook\\Attributes\\Filter;\n\n// Example of using an action hook\n#[Action('init')]\nfunction basic_action(): string {\n\treturn 'something...';\n}\n\n// Example of using a filter hook\n#[Filter('the_content')]\nfunction basic_filter(): string {\n\treturn 'something...';\n}\n\n// You can also attach a priority and args\n#[Action('init', priority: 20, args: 4)]\nfunction advanced_action( string $arg1, int $arg2, bool $arg3, array $arg4 ): string\n\treturn 'something...';\n}\n```\n\nNot on PHP8 yet? You can use annotations instead\n\n```php\nuse BoxUk\\WpHookAttributes\\Hook\\Annotations\\Action;\nuse BoxUk\\WpHookAttributes\\Hook\\Annotations\\Filter;\n\n// Example of using an action hook\n/**\n * @Action(\"init\")\n */\nfunction basic_action(): string {\n\treturn 'something...';\n}\n\n// Example of using a filter hook\n/**\n * @Filter(\"the_content\") \n */\nfunction basic_filter(): string {\n\treturn 'something...';\n}\n\n// You can also attach a priority and args\n/**\n * @Action(\"init\", priority=\"20\", args=\"4\")\n */\nfunction advanced_action( string $arg1, int $arg2, bool $arg3, array $arg4 ): string\n\treturn 'something...';\n}\n```\n\n\u003e Note: Anything lower than PHP 7.4 is not supported.\n\n## Registering a namespace or prefix (highly recommended)\n\nYou likely want to register a namespace or prefix to ensure it only looks for attributes/annotations for your code. You can do so via the following hook:\n\n**If you're using annotations and don't do this it will likely be extremely slow**\n\n```php\n// Namespace\nadd_filter( 'wp_hook_attributes_registered_namespaces', function(): array {\n\treturn [\n\t\t'BoxUk\\Mu\\Plugins',\n\t];\n});\n\n// Prefix\nadd_filter( 'wp_hook_attributes_registered_prefixes', function(): array {\n\treturn [\n\t\t'boxuk_',\n\t];\n});\n```\n\n\u003e It does a `stripos()` comparison, so you can just put the first part of the namespace/prefix.\n\n## Registering files and classes\n\nCurrently only works with defined functions and declared classes that are registered before the `init` hook. To get around this you can register function files or classes manually using the following hooks. This will need to be done prior to `init` though, or the resolver will need to be called manually (details below).\n\n```php\nadd_filter( 'wp_hook_attributes_registered_function_files', function( array $registered_files ): array {\n\treturn array_merge(\n\t\t$registered_files,\n\t\t\t[\n\t\t\t\t'path/to/my/file/with/functions.php'\n\t\t\t]\n\t);\n});\n\nadd_filter( 'wp_hook_attributes_registered_classes', function( array $registered_classes ): array {\n\treturn array_merge(\n\t\t$registered_classes,\n\t\t\t[\n\t\t\t\tRegistrationService::class,\n\t\t\t]\n\t);\n});\n```\n\n## Ignoring existing annotation names\n\nSometimes you may get errors when using annotations that an existing annotation hasn't been imported. This is because sometimes you find non-standard annotations or docblock parameters that we need to ignore. \n\nSome common WordPress and related libraries are ignored by default, but it won't cover everything.\n\nYou can ignore any custom annotations you need to with the following hook:\n\n```php\nadd_filter( \n\t'wp_hook_attributes_annotation_ignores',\n\tfunction( array $existing_ignores ): array {\n\t\t$existing_ignores[] = 'my-custom-annotation';\n\t\treturn $existing_ignores;\n\t}\n);\n```\n\n## Limitations\n\n### Attributes on hooks prior to `init` require a bit more work\n\nIf you wish to use hooks prior to the `init` hook, for example `muplugins_loaded` you will not be able to use attributes for these without a bit more effort. As they would have already been called by the point the hook resolver is called, you will need to call the hook resolver yourself manually. For example, let's say you have a hook on `muplugins_loaded` which is a pre-init hook.\n\n```php\n/**\n * @ActionAnnotation(\"muplugins_loaded\")\n */\n#[Action('muplugins_loaded')]\nfunction muplugins_loaded_action(): void\n{\n    echo 'on muplugins_loaded action';\n}\n```\n\nThe `muplugins_loaded` hook would have already been called by the time our `init` hook is called which calls the hook resolver. So in these scenarios, you'll need to call the hook resolver manually, e.g.\n\n```php\n/**\n * @ActionAnnotation(\"muplugins_loaded\")\n */\n#[Action('muplugins_loaded')]\nfunction muplugins_loaded_action(): void\n{\n    echo 'on muplugins_loaded action';\n}\n\n// Some place earlier than `muplugins_loaded`, maybe a `000-my-project.php` or something within `mu-plugins`.\n( new WordPressHookAttributes() )();\n```\n\n\u003e See the next limitation as to why we don't load the resolver this early by default.\n\nThe main hooks that this applies to is (but not limited to):\n\n```\nmuplugins_loaded\nregistered_taxonomy\nregistered_post_type\nplugins_loaded\nsanitize_comment_cookies\nsetup_theme\nunload_textdomain\nload_textdomain\nafter_setup_theme\nauth_cookie_malformed\nauth_cookie_valid\nset_current_user\n```\n\n\u003e Source: http://rachievee.com/the-wordpress-hooks-firing-sequence/\n\n### Functions/methods must be registered before the `init` hook\n\nAttributes should work for any function/method registered before the `init` hook is called. Any function/method that is registered as part of an `mu-plugin` or a `theme` should work as the hooks to load these are called prior to `init`.\n\nWhat won't work is any function/method that is registered after the `init` hook, for example the following won't work because `wp_loadded` is called after `init` and thus the functions within `my-functions.php` won't be registered in time:\n\n```php\n// This will not work.\nadd_action( 'wp_loaded', function() {\n    require_once 'my-functions.php';\n});\n```\n\nYou can register files manually, but again, this must be done before `init`, so to fix the above you can do:\n\n```php\nadd_action( 'muplugins-loaded', function() {\n    add_filter( 'wp_hook_attributes_registered_function_files', function() {\n        return [\n            'my-functions.php';\n        ];\n    });\n});\n```\n\nSimilarly, simply requiring it will work also:\n\n```php\nadd_action( 'muplugins-loaded', function() {\n    require_once 'my-functions.php';\n});\n```\n\n### Non-static methods are not supported\n\nIf you have a method which relies on an instance of the current object, for examples:\n\n```php\nclass Example {\n    private $foo = 'world';\n    \n    public function hello(): string {\n        return 'Hello ' . $this-\u003efoo;\n    }\n}\n```\n\nYou are able to set up a callback using an instance of `Example`, e.g. \n\n```php\n$example = new Example();\n$callback = [ $example, 'hello' ];\n```\n\nHowever, this isn't supported with this library because it cannot make an assumption on how it instantiates the class. Therefore, only static methods will work. It also requires methods are marked as static even if they are implicitly static. This is good practice anyway as using a method as static if not explicitly declared will raise a PHP Deprecated on PHP 7.4 and a Fatal Error on PHP 8.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboxuk%2Fwp-hook-attributes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fboxuk%2Fwp-hook-attributes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboxuk%2Fwp-hook-attributes/lists"}