CallbackHelper
The CallbackHelper provides a unified way to execute and register callbacks throughout the library. It supports multiple callback formats and provides a consistent API for callback management.
Overview
Section titled “Overview”CallbackHelper is the central callback management system used by:
- DataMapper - Template expression callbacks
- SimpleDTO Attributes -
#[Visible],#[WhenCallback] - Hooks - DataMapper hook callbacks
- Filters - Custom filter callbacks
Registration
Section titled “Registration”register()
Section titled “register()”Register a named callback that can be used in template expressions.
use event4u\DataHelpers\Support\CallbackHelper;
CallbackHelper::register('slugify', function($params) { return strtolower(str_replace(' ', '-', $params->value));});
// Use in template$template = ['slug' => '{{ article.title | callback:slugify }}'];registerOrReplace()
Section titled “registerOrReplace()”Register a callback or replace an existing one.
CallbackHelper::registerOrReplace('slugify', function($params) { return strtolower(preg_replace('/[^a-z0-9]+/', '-', $params->value));});Retrieve a registered callback.
$callback = CallbackHelper::get('slugify');
if ($callback !== null) { // Callback exists}Check if a callback is registered.
if (CallbackHelper::has('slugify')) { // Callback exists}unregister()
Section titled “unregister()”Remove a registered callback.
CallbackHelper::unregister('slugify');clear()
Section titled “clear()”Remove all registered callbacks.
CallbackHelper::clear();getRegisteredNames()
Section titled “getRegisteredNames()”Get all registered callback names.
$names = CallbackHelper::getRegisteredNames();// ['slugify', 'uppercase', 'formatDate', ...]count()
Section titled “count()”Get the number of registered callbacks.
$count = CallbackHelper::count();Execution
Section titled “Execution”execute()
Section titled “execute()”Execute a callback with unified logic. Supports multiple callback formats.
use event4u\DataHelpers\Support\CallbackHelper;
// Execute registered callback$result = CallbackHelper::execute('slugify', $params);
// Execute static method$result = CallbackHelper::execute('MyClass::method', $arg1, $arg2);
// Execute instance method$result = CallbackHelper::execute('methodName', $instance, $arg1);
// Execute closure$result = CallbackHelper::execute(fn($x) => $x * 2, 5);Execution Priority
Section titled “Execution Priority”CallbackHelper::execute() resolves callbacks in the following order:
- Resolve
static::method- If callback is'static::method'and first arg is an object, resolve to actual class - Registered callbacks - Check if callback is registered via
register() - Static methods -
'Class::method'or[Class::class, 'method'] - Array callables -
[$instance, 'method'] - Instance methods - Method name with instance in args (uses reflection for private/protected)
- Global functions -
'function_name' - Closures -
fn($x) => $x * 2 - Invokable objects - Objects with
__invoke()method
Callback Formats
Section titled “Callback Formats”Registered Callbacks
Section titled “Registered Callbacks”CallbackHelper::register('upper', fn($p) => strtoupper($p->value));
// Use in template$template = ['name' => '{{ user.name | callback:upper }}'];Static Methods
Section titled “Static Methods”class StringHelper{ public static function slugify(string $value): string { return strtolower(str_replace(' ', '-', $value)); }}
// String syntax$result = CallbackHelper::execute('StringHelper::slugify', 'Hello World');
// Array syntax$result = CallbackHelper::execute([StringHelper::class, 'slugify'], 'Hello World');Static Method with static::
Section titled “Static Method with static::”class UserDTO extends SimpleDTO{ #[Visible(callback: 'static::canViewEmail')] public readonly string $email;
public static function canViewEmail(mixed $dto, mixed $context): bool { return $context?->role === 'admin'; }}
// CallbackHelper automatically resolves 'static::' to the actual classInstance Methods
Section titled “Instance Methods”class UserDTO extends SimpleDTO{ #[Visible(callback: 'canViewEmail')] public readonly string $email;
private function canViewEmail(mixed $context): bool { return $context?->role === 'admin'; }}
// CallbackHelper uses reflection to call private/protected methodsArray Callables with Instance
Section titled “Array Callables with Instance”$checker = new PermissionChecker();
// Array syntax with instance$result = CallbackHelper::execute([$checker, 'canView'], $user, $context);Global Functions
Section titled “Global Functions”function slugify(string $value): string{ return strtolower(str_replace(' ', '-', $value));}
$result = CallbackHelper::execute('slugify', 'Hello World');Closures
Section titled “Closures”$callback = fn($value) => strtoupper($value);
$result = CallbackHelper::execute($callback, 'hello');// 'HELLO'Invokable Objects
Section titled “Invokable Objects”class Slugifier{ public function __invoke(string $value): string { return strtolower(str_replace(' ', '-', $value)); }}
$slugifier = new Slugifier();$result = CallbackHelper::execute($slugifier, 'Hello World');Examples
Section titled “Examples”Template Expression Callbacks
Section titled “Template Expression Callbacks”use event4u\DataHelpers\DataMapper;use event4u\DataHelpers\Support\CallbackHelper;
// Register callbacksCallbackHelper::register('slugify', fn($p) => strtolower(str_replace(' ', '-', $p->value)));CallbackHelper::register('excerpt', fn($p) => substr($p->value, 0, 100) . '...');
// Use in template$template = [ 'slug' => '{{ article.title | callback:slugify }}', 'excerpt' => '{{ article.content | callback:excerpt }}',];
$result = DataMapper::from($article) ->template($template) ->map() ->getTarget();Attribute Callbacks
Section titled “Attribute Callbacks”use event4u\DataHelpers\SimpleDTO;use event4u\DataHelpers\SimpleDTO\Attributes\Visible;use event4u\DataHelpers\SimpleDTO\Attributes\WhenCallback;
class UserDTO extends SimpleDTO{ public function __construct( public readonly string $name,
// Instance method callback #[Visible(callback: 'canViewEmail')] public readonly string $email,
// Static method callback #[Visible(callback: 'static::canViewPhone')] public readonly string $phone,
// Conditional property #[WhenCallback('static::isAdult')] public readonly ?string $adultContent = null, ) {}
private function canViewEmail(mixed $context): bool { return $context?->role === 'admin'; }
public static function canViewPhone(mixed $dto, mixed $context): bool { return $context?->role === 'admin' || $context?->role === 'manager'; }
public static function isAdult(object $dto, mixed $value, array $context): bool { return ($dto->age ?? 0) >= 18; }}Error Handling
Section titled “Error Handling”CallbackHelper::execute() throws InvalidArgumentException if the callback cannot be resolved:
try { $result = CallbackHelper::execute('nonExistentFunction', $arg);} catch (InvalidArgumentException $e) { // Handle error}For attribute callbacks (#[Visible], #[WhenCallback]), exceptions are caught automatically and the property is hidden or excluded.
Migration from CallbackRegistry
Section titled “Migration from CallbackRegistry”CallbackRegistry has been removed. Use CallbackHelper instead:
// ❌ Old (removed)use event4u\DataHelpers\DataMapper\Pipeline\CallbackRegistry;CallbackRegistry::register('upper', fn($p) => strtoupper($p->value));
// ✅ Newuse event4u\DataHelpers\Support\CallbackHelper;CallbackHelper::register('upper', fn($p) => strtoupper($p->value));All methods have the same signature, so migration is straightforward.