Actions & Filters
Attribute-based hooks
Section titled “Attribute-based hooks”You can define action and filter hooks using PHP attributes. This provides a more concise way to define hooks within your classes.
Declarate with artisan
Section titled “Declarate with artisan”You can create a new attribute-based hook class using the pollora:make-action or pollora:make-filter Artisan commands:
# Create a new action hook classphp artisan pollora:make-action MyActionClass
# Create a new filter hook classphp artisan pollora:make-filter MyFilterClassAction hooks
Section titled “Action hooks”To define an action hook, use the Action attribute from the Pollora\Attributes\Action namespace:
<?php
namespace App\Cms\Hooks;
use Pollora\Attributes\Action;
class MyActionClass{ #[Action('init', priority: 20)] public function handleInit(): void { // Code to execute for the 'init' WordPress action }}Multiple action hooks can be declared for the same method:
#[Action('init', priority: 10)]#[Action('wp_loaded', priority: 15)]public function setup(): void{ // Runs on multiple hooks}Filter hooks
Section titled “Filter hooks”To define a filter hook, use the Filter attribute from the Pollora\Attributes\Filter namespace:
<?php
namespace App\Cms\Hooks;
use Pollora\Attributes\Filter;
class MyFilterClass{ #[Filter('the_content', priority: 10)] public function handleTheContent(string $content): string { return str_replace('ugly', 'shiny', $content); }}All classes inside the app/Cms/Hooks folder with hook attributes are automatically discovered and registered.
Action and Filter facades
Section titled “Action and Filter facades”Pollora provides two powerful facades, Action and Filter, to interact with WordPress hooks in a structured and maintainable way. These facades simplify the registration, execution, and management of actions and filters, while ensuring dependency injection and class-based organization.
Registering an action or filter
Section titled “Registering an action or filter”To register an action or filter, use the respective add() method:
use Pollora\Support\Facades\Action;use Pollora\Support\Facades\Filter;
// Register an actionAction::add('init', [App\Hooks\InitHandler::class, 'boot']);
// Register a filter explicitly specifying the methodFilter::add('the_content', [App\Hooks\ContentHandler::class, 'modify']);
// Register a filter without specifying the methodFilter::add('the_content', App\Hooks\ContentHandler::class);When passing a class reference alone, Pollora will automatically call a method following Laravel’s naming conventions: it will look for theContent() inside ContentHandler. If a method is explicitly provided, that method will be called instead. If the method is not found, an exception is thrown, specifying the missing method.
Using functions, closures, or instances
Section titled “Using functions, closures, or instances”Actions and filters can also be registered using functions, closures, or object instances:
// Functionfunction custom_callback() { // Code...}Action::add('init', 'custom_callback');
// ClosureFilter::add('the_content', function($content) { return strtoupper($content);});
// Object instance$handler = new App\Hooks\ContentHandler();Filter::add('the_content', [$handler, 'modify']);Constructor injection
Section titled “Constructor injection”Pollora automatically resolves dependencies when registering actions and filters using a class reference. Both the attribute-based discovery path and the imperative API (facades) support constructor injection through the Laravel container:
namespace App\Cms\Hooks;
use Illuminate\Http\Request;use App\Services\ContentProcessor;
class ContentHandler { protected $request; protected $processor;
public function __construct(Request $request, ContentProcessor $processor) { $this->request = $request; $this->processor = $processor; }
public function theContent($content) { return $this->processor->process($content); }
public function modify($content) { return strtoupper($content); }}This class can be registered in two ways:
// Calls the `theContent` method automaticallyFilter::add('the_content', App\Hooks\ContentHandler::class);
// Calls the `modify` method explicitlyFilter::add('the_content', [App\Hooks\ContentHandler::class, 'modify']);Executing actions and filters
Section titled “Executing actions and filters”To execute an action, use do(), which functions like do_action() in WordPress:
Action::do('custom_event', $arg1, $arg2);To apply a filter, use apply(), similar to apply_filters():
$modified_value = Filter::apply('custom_filter', $original_value, $arg1);Checking existence
Section titled “Checking existence”To verify if an action or filter is registered:
if (Action::exists('custom_event')) { // Code...}
if (Filter::exists('custom_filter')) { // Code...}Removing actions and filters
Section titled “Removing actions and filters”Actions and filters can be removed using remove():
Action::remove('init', [App\Hooks\InitHandler::class, 'boot']);Filter::remove('the_content', [App\Hooks\ContentHandler::class, 'modify']);Note: If an action or filter was registered with a specific priority, the same priority must be specified when removing it.
Retrieving callbacks
Section titled “Retrieving callbacks”To get the registered callbacks for an action or filter:
$callbacks = Action::callbacks('init');$filterCallbacks = Filter::callbacks('the_content');Deferred callbacks
Section titled “Deferred callbacks”Pollora aligns with WordPress behavior for callback registration: callbacks that are not yet callable at registration time (e.g., functions defined by plugins loaded later) are accepted without throwing an exception. Validation occurs at execution time, just like WordPress’s native add_action()/add_filter().
// This works even if the function doesn't exist yet —// it will be resolved when the hook fires.Action::add('init', 'my_plugin_function');Service access
Section titled “Service access”The Action and Filter services are registered as singletons in the container and can be accessed via facades or dependency injection:
// Via facadesuse Pollora\Support\Facades\Action;use Pollora\Support\Facades\Filter;
// Via dependency injectionuse Pollora\Hook\Domain\Contracts\Action as ActionContract;use Pollora\Hook\Domain\Contracts\Filter as FilterContract;
class MyService { public function __construct( private ActionContract $action, private FilterContract $filter ) {}}