illuminate/macroable
Illuminate Macroable adds Laravel’s Macroable trait, letting you register custom methods (macros) on classes at runtime. Extend core components or your own objects without inheritance, enabling flexible, discoverable APIs and clean, centralized extension points.
The illuminate/macroable trait enables adding runtime methods to classes without inheritance—ideal for extending core PHP or Laravel classes (e.g., Collection, Stringable, or custom classes) with domain-specific utilities. First, include the trait in your class:
use Illuminate\Support\Traits\Macroable;
class OrderProcessor
{
use Macroable;
}
Then, register macros—static closures bound to a class—using the macro() method:
OrderProcessor::macro('totalWithTax', function (float $taxRate) {
return $this->subtotal * (1 + $taxRate);
});
Your first use case: extend a Stringable instance with custom formatting (e.g., toSnakeCase if not in Str). The most common entry point is using Laravel’s built-in macroable classes like Str or Str::class (though Str itself is macroable via Macroable internally).
Macro Registration Bootstrap: Register macros in service providers (e.g., AppServiceProvider::boot()) or dedicated macro service providers for clarity. This ensures macros are available app-wide after boot.
Per-Context Extensions: Use macros for context-specific logic—e.g., macros on Collection for domain-specific aggregations:
Collection::macro('activeUsers', function () {
return $this->where('status', 'active');
});
$users = User::all()->activeUsers();
Testing Macros: Store macros in closures for easy mocking—especially useful for mocking side-effect-prone logic (e.g., macros on Http\Client\Response).
Namespacing via Classes: Group related macros by class (e.g., StringMacros, CollectionMacros) and register them in a macro trait for reusability.
Factory Macros: Register macros on factory classes (e.g., UserFactory::macro(...)) to define custom stateful definitions.
PHP 8.2+ Requirement: Ensure your environment meets the ^8.2 requirement—older PHP versions will silently fail or error on trait resolution.
Macro Overwrites: Calling macro() multiple times for the same name silently overwrites the previous macro. Use hasMacro() before registering to avoid unintentional overrides.
$this Binding: Macros receive $this as the instance they’re called on—ensure your closure doesn’t rely on $this being a specific class without type safety.
Debugging: Macros aren’t visible in reflection or IDE autocomplete. Use debug_backtrace() or custom logging in macro definitions to trace usage at runtime.
Performance: Macros are resolved at runtime—avoid hot-path macros in tight loops. Cache compiled macros via opcache or static caching if needed.
Extension Points: Since Macroable is a trait, it must be used—not extended. You cannot override macro() or hasMacro() directly; instead, define helper traits or wrapper classes.
How can I help you explore Laravel packages today?