Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Macroable Laravel Package

spatie/macroable

Add methods to any class at runtime with Spatie’s Macroable trait. Register macros with closures or callables and call them like native methods; macros are bound to the class instance for access to $this. Inspired by Laravel’s Macroable implementation.

View on GitHub
Deep Wiki
Context7

Getting Started

Start by installing the package via Composer:

composer require spatie/macroable

Then apply the Spatie\Macroable\Macroable trait to any class you want to extend dynamically. The most immediate use case is augmenting existing classes (like service classes or value objects) with ad-hoc functionality without modifying their source — ideal for prototyping, testing, or plugin-style behavior injection. For example:

use Spatie\Macroable\Macroable;

class MyService
{
    use Macroable;
    
    public function doSomething() { return 'original'; }
}

$service = new MyService();
$service::macro('extended', fn() => 'extra behavior');
echo $service->extended(); // 'extra behavior'

Implementation Patterns

  • Runtime extensions for testing: Monkey-patch methods during test setup to isolate behavior or simulate dependencies.
  • Plugin-like features: Add domain-specific behavior conditionally (e.g., enable analytics or logging macros only in certain environments).
  • Mixin classes: Group related macros into a dedicated class returning closures — useful for modular, reusable extension bundles (e.g., StringMacros, CollectionMacros).
  • Laravel integration: Extend framework classes (like Str, Collection) where Laravel’s core already uses Macroable, or build your own macroable services (e.g., custom mailers or payment gateways).
  • Method aliases & conveniences: Provide syntactic sugar — e.g., User::macro('fullName', fn() => "{$this->first} {$this->last}").

Gotchas and Tips

  • Binding context: Closures passed to macro() are bound to the instance’s $this, so they can access properties and other methods — but be cautious with closures that capture variables; they’re evaluated at macro registration time, not call time.
  • Static vs. instance methods: Macros are always instance methods — ::macro() registers them on the class, but they’re invoked on instances (e.g., $obj->macroName()).
  • Overwriting macros: Calling macro('name', ...) again overwrites the previous macro — no warnings are issued. Use hasMacro() to guard against accidental overwrites.
  • IDE autocomplete: Static analyzers won’t know about dynamic methods. Use PHPDoc annotations (e.g., @method string someMacro()) or tools like barryvdh/laravel-ide-helper to improve DX.
  • Testing macros: Macro registrations persist globally for the class — reset them between tests using unsetMacro() or flushMacros() to avoid test pollution.
  • Performance: Macros add minimal overhead, but excessive runtime modification may complicate caching or Ahead-of-Time compilation. Use sparingly in hot paths.
  • PHP version: Requires PHP 8.3+ (v3.0+); ensure your stack matches — older PHP versions (8.2 and below) need v2.x.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport