pollora / attributes
PHP attributes to declare WordPress post types, taxonomies, hooks, REST routes, meta, roles, schedules and more. Declarations only: they run without the framework.
Requires
- php: ^8.3
- ext-mbstring: *
- pollora/abilities: ^1.0
- pollora/ajax: ^1.1
Requires (Dev)
- illuminate/support: ^13.0
- laravel/pint: ^1.22.1
- pestphp/pest: ^3.8.2
- phpstan/phpstan: ^2.1.16
- szepeviktor/phpstan-wordpress: ^2.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-15 13:27:24 UTC
README
The PHP attributes that declare WordPress components as code: #[PostType], #[Taxonomy], #[Action], #[Filter], #[WpRestRoute], #[Meta], #[Role], #[Schedule], #[Ajax], #[Ability], #[BlockBinding], #[WpCli] and the attributes that refine them.
They are declarations only. Each attribute holds its values and, for post types and taxonomies, says which registration arguments it sets; registering is left to the code that reads them. A plugin can declare its components without installing a framework, and an IDE or a static analyser can read them alone.
Part of Pollora, the Laravel framework for WordPress, which discovers these attributes and registers what they declare. See Auto-discovery and the post type attributes reference.
Installation
composer require pollora/attributes
Requires PHP 8.3+ and mbstring. It brings pollora/ajax and pollora/abilities, whose AjaxAccess and Behaviour enumerations #[Ajax] and #[Ability] take; both depend on PHP alone.
Declaring
use Pollora\Attributes\Action; use Pollora\Attributes\PostType; use Pollora\Attributes\PostType\AdminCol; use Pollora\Attributes\PostType\HasArchive; use Pollora\Attributes\PostType\ShowInRest; use Pollora\Attributes\PostType\Supports; #[PostType('book')] #[HasArchive('library')] #[ShowInRest] #[Supports(['title', 'editor', 'thumbnail'])] final class Book { #[AdminCol('isbn', 'ISBN', sortable: true)] public function isbnColumn(int $postId): string { return (string) get_post_meta($postId, 'isbn', true); } #[Action('save_post_book')] public function onSave(int $postId): void {} }
Reading
Post type and taxonomy attributes implement ConfiguresArguments: given the registration arguments gathered so far, they return them with their own contribution. Method attributes such as #[AdminCol] or #[RegisterMetaBoxCb] implement ConfiguresArgumentsWithMethod and are handed the decorated method as a callback.
use Pollora\Attributes\Contracts\ConfiguresArguments; use Pollora\Attributes\Contracts\ConfiguresArgumentsWithMethod; use Pollora\Attributes\PostType; $class = new ReflectionClass(Book::class); $postType = $class->getAttributes(PostType::class)[0]->newInstance(); $arguments = []; foreach ($class->getAttributes() as $attribute) { $instance = $attribute->newInstance(); if ($instance instanceof ConfiguresArguments) { $arguments = $instance->configureArguments($arguments); } } foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { foreach ($method->getAttributes() as $attribute) { $instance = $attribute->newInstance(); if ($instance instanceof ConfiguresArgumentsWithMethod) { $arguments = $instance->configureArguments($arguments, [new Book, $method->getName()]); } } } register_post_type($postType->resolveSlug(Book::class), $arguments); // ['has_archive' => 'library', 'show_in_rest' => true, 'supports' => [...], 'admin_cols' => ['isbn' => [...]]]
resolveSlug() derives the slug from the class name when none is given (Book → book, kebab case, 20 characters at most), as Pollora does. The other attributes are plain values: #[Action('init', priority: 20)] exposes $hook and $priority.
Public API
The attribute classes, their constructor parameters and public properties, and the Pollora\Attributes\Contracts\* interfaces follow semantic versioning. Pollora\Attributes\Support\* is internal.
The package also carries the value types the attributes take, under the class names Pollora has always used: Pollora\Schedule\Every and Interval, Pollora\Role\Domain\Enums\Access, Pollora\Meta\Domain\Enums\Control and Pollora\BlockBinding\Domain\Enums\BindingFieldType.
Testing
composer test # unit tests, PHPStan, Pint
License
MIT. See LICENSE.