Skip to content

Actions & Filters

You can define action and filter hooks using PHP attributes. This provides a more concise way to define hooks within your classes.

You can create a new attribute-based hook class using the pollora:make-action or pollora:make-filter Artisan commands:

Terminal window
# Create a new action hook class
php artisan pollora:make-action MyActionClass
# Create a new filter hook class
php artisan pollora:make-filter MyFilterClass

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
}

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.

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.

To register an action or filter, use the respective add() method:

use Pollora\Support\Facades\Action;
use Pollora\Support\Facades\Filter;
// Register an action
Action::add('init', [App\Hooks\InitHandler::class, 'boot']);
// Register a filter explicitly specifying the method
Filter::add('the_content', [App\Hooks\ContentHandler::class, 'modify']);
// Register a filter without specifying the method
Filter::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.

Actions and filters can also be registered using functions, closures, or object instances:

// Function
function custom_callback() {
// Code...
}
Action::add('init', 'custom_callback');
// Closure
Filter::add('the_content', function($content) {
return strtoupper($content);
});
// Object instance
$handler = new App\Hooks\ContentHandler();
Filter::add('the_content', [$handler, 'modify']);

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 automatically
Filter::add('the_content', App\Hooks\ContentHandler::class);
// Calls the `modify` method explicitly
Filter::add('the_content', [App\Hooks\ContentHandler::class, 'modify']);

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);

To verify if an action or filter is registered:

if (Action::exists('custom_event')) {
// Code...
}
if (Filter::exists('custom_filter')) {
// Code...
}

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.

To get the registered callbacks for an action or filter:

$callbacks = Action::callbacks('init');
$filterCallbacks = Filter::callbacks('the_content');

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');

The Action and Filter services are registered as singletons in the container and can be accessed via facades or dependency injection:

// Via facades
use Pollora\Support\Facades\Action;
use Pollora\Support\Facades\Filter;
// Via dependency injection
use 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
) {}
}