Search by

pollora / attributes

pollora

PHP attributes to declare WordPress post types, taxonomies, hooks, REST routes, meta, roles, schedules and more. Declarations only: they run without the framework.

Package info

github.com/Pollora/attributes

Homepage

pkg:composer/pollora/attributes

Statistics

Installs: 673

Dependents: 3

Suggesters: 0

Stars: 1

Open Issues: 0

v0.1.1 2026-10-15 13:27 UTC

This package is auto-updated.

Last update: 2026-10-15 13:27:24 UTC


README

Pollora Attributes: declare post types, taxonomies, hooks and REST routes as PHP attributes

Latest version Total downloads Tests License

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.