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

hyperf/macroable

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require hyperf/macroable
    

    Register the service provider in config/autoload/services.php:

    'providers' => [
        Hyperf\Macroable\MacroableServiceProvider::class,
    ],
    
  2. First Use Case: Extend a class (e.g., App\Services\MyService) with macro capabilities:

    use Hyperf\Macroable\Macroable;
    
    class MyService extends Macroable
    {
        // Your existing methods
    }
    
  3. Define a Macro:

    MyService::macro('customMethod', function () {
        return 'Macro result';
    });
    
  4. Use the Macro:

    $result = (new MyService())->customMethod();
    

Where to Look First

  • Documentation: Check the Laravel Macroable docs (since this is a port).
  • Source: Review Hyperf\Macroable\Macroable trait for core functionality.
  • Examples: Look at tests/ for usage patterns.

Implementation Patterns

Common Workflows

  1. Dynamic Method Injection: Use macros to add methods to classes without modifying their source:

    // Add a 'toJson' macro to a model
    App\Models\User::macro('toJson', function () {
        return json_encode($this->toArray());
    });
    
  2. Service-Level Extensions: Extend Hyperf services (e.g., Container, Request) globally:

    // In a service provider's boot method
    $container->get(\Hyperf\Contract\ContainerInterface::class)
        ->macro('singletonWith', function ($abstract, $concrete = null) {
            return $this->singleton($abstract, $concrete);
        });
    
  3. Conditional Macros: Define macros conditionally (e.g., based on environment):

    if (app()->environment('local')) {
        App\Models\User::macro('debug', function () {
            return $this->toArray() + ['debug' => true];
        });
    }
    
  4. Macro Composition: Chain macros or reuse logic:

    App\Models\User::macro('fullName', function () {
        return "{$this->first_name} {$this->last_name}";
    });
    
    App\Models\User::macro('greet', function () {
        return "Hello, {$this->fullName()}!";
    });
    

Integration Tips

  • Hyperf-Specific: Use macros to extend Hyperf’s built-in components (e.g., Request, Response):

    \Hyperf\HttpMessage\Stream\SwooleStream::macro('toJson', function () {
        return json_encode($this->getContents());
    });
    
  • Middleware: Add macros to middleware for reusable logic:

    class CustomMiddleware implements MiddlewareInterface {
        use Macroable;
    
        public function __construct() {
            $this->macro('logRequest', function ($request) {
                logger()->info('Custom log:', ['path' => $request->getUri()]);
            });
        }
    }
    
  • Testing: Mock macros in tests:

    $mock = Mockery::mock(App\Models\User::class);
    $mock->shouldReceive('customMacro')->andReturn('Mocked!');
    

Gotchas and Tips

Pitfalls

  1. Namespace Collisions: Macros with the same name across classes will override each other. Use unique names or namespaces:

    // Avoid:
    App\Models\User::macro('format', ...);
    App\Models\Post::macro('format', ...); // Overrides User's macro
    
    // Prefer:
    App\Models\User::macro('userFormat', ...);
    
  2. Late Binding Issues: Macros defined in traits or parent classes may not be available in child classes unless explicitly extended:

    // Parent class
    class ParentClass {
        use Macroable;
    }
    
    // Child class (macros not inherited by default)
    class ChildClass extends ParentClass {
        // Must redefine macros if needed
    }
    
  3. Performance: Overusing macros can bloat method lookups. Benchmark critical paths.

  4. Static Analysis Tools: Some static analyzers (e.g., PHPStan) may flag macros as "undefined methods." Add @method PHPDoc annotations:

    /**
     * @method string customMacro()
     */
    class MyClass {}
    

Debugging

  • Check Registered Macros: Use get_macros() to inspect registered macros:

    $macros = (new MyService())->get_macros();
    
  • Disable Macros Temporarily: Override the macro() method to debug:

    MyService::macro('macro', function ($name, $macro) {
        logger()->debug("Macro registered: $name");
        return parent::macro($name, $macro);
    });
    

Extension Points

  1. Custom Macro Storage: Extend the Macroable trait to use a custom storage backend (e.g., database):

    class CustomMacroable {
        protected $macros = [];
    
        public function loadMacros() {
            $this->macros = Cache::get('app_macros', []);
        }
    
        public function macro($name, $macro) {
            $this->macros[$name] = $macro;
            Cache::put('app_macros', $this->macros);
        }
    }
    
  2. Macro Events: Trigger events when macros are registered/called:

    MyService::macro('onMacroRegistered', function ($name) {
        event(new MacroRegistered($name));
    });
    
    MyService::macro('customMethod', function () {
        $this->onMacroRegistered('customMethod');
        return 'Result';
    });
    
  3. Hyperf Context: Leverage Hyperf’s DI container to resolve dependencies in macros:

    MyService::macro('withDependency', function () {
        return $this->container->get(MyDependency::class);
    });
    

Config Quirks

  • Service Provider: Ensure the MacroableServiceProvider is registered after the class you’re extending (if using autoloading).
  • Autoloading: Hyperf’s OPcache may need a restart after adding new macros:
     php bin/hyperf.php cache:warmup
    
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.
anousss007/vigilance
supportpal/eloquent-model
ardenexal/fhir-models
laravel-at/laravel-image-sanitize
romalytar/yammi-audit-log-laravel
ardenexal/fhir-validation
arshaviras/weather-widget
laravel-chronicle/core
sunchayn/nimbus
daikazu/eloquent-salesforce-objects
unseen-codes/chat
romalytar/yammi-jobs-monitoring-laravel
kisame76/filament-db-table-state
nqxcode/laravel-lucene-search
dpfx/laravel-livewire-wizards
workos/workos-php-laravel
sofa/laravel-global-scope
nawasara/auth-primitives
adhocrat-io/arkhe-main
make-dev/orca-harpoon