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

Tappable Laravel Package

hyperf/tappable

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require hyperf/tappable
    

    Ensure hyperf/framework is installed (this package extends Hyperf’s core).

  2. First Use Case: Extend a Hyperf class (e.g., a service or command) with tappable macros. Example:

    use Hyperf\Tappable\Macroable;
    
    class MyService extends AbstractService implements Macroable
    {
        // Inherits macroable traits
    }
    
    MyService::macro('log', function ($message) {
        \Hyperf\Logger\LoggerFactory::get('default')->info($message);
    });
    
    // Usage:
    $service = new MyService();
    $service->log('Hello, tappable!');
    
  3. Key Files:

    • Review Macroable.php for trait methods.
    • Check MacroableServiceProvider.php (if included) for global macros.

Implementation Patterns

Common Workflows

  1. Macroable Services: Attach macros to Hyperf services (e.g., Request, Response, Container).

    \Hyperf\HttpServer\Request::macro('isAdmin', function () {
        return $this->input('role') === 'admin';
    });
    
  2. Command Extensions: Extend Hyperf commands with reusable logic:

    \Hyperf\Command\Command::macro('askForConfirmation', function ($question) {
        if (!\Hyperf\Support\env('APP_ENV') === 'production') {
            return $this->ask($question, 'no') === 'yes';
        }
        return true;
    });
    
  3. Container Macros: Dynamically bind services or modify container behavior:

    \Hyperf\Container\Container::macro('singletonIf', function ($abstract, $concrete, $condition) {
        if ($condition) {
            $this->singleton($abstract, $concrete);
        }
    });
    
  4. Middleware Macros: Add reusable middleware logic:

    \Hyperf\HttpServer\Middleware\Middleware::macro('validateJson', function () {
        return function ($request, $next) {
            if (!$request->isJson()) {
                return \Hyperf\HttpServer\Response::json(['error' => 'Invalid JSON']);
            }
            return $next($request);
        };
    });
    

Integration Tips

  • Dependency Injection: Use macros to inject context-aware logic without modifying core classes.
  • Testing: Mock macroable classes in PHPUnit by resetting macros:
    MyService::flushMacros();
    
  • Configuration: Store macro definitions in a dedicated config file (e.g., config/macros.php) for organization.

Gotchas and Tips

Pitfalls

  1. Macro Overwriting: Macros with the same name will overwrite each other. Use unique names or namespaces:

    MyService::macro('App\Macros\log', function () { ... });
    
  2. Static Context: Macros are static; avoid relying on instance state unless explicitly passed:

    // Bad: Assumes $this refers to the macroable instance.
    MyService::macro('getUser', function () {
        return $this->user; // May fail if called statically.
    });
    
    // Good: Explicitly pass context.
    MyService::macro('getUser', function ($service) {
        return $service->user;
    });
    
  3. Hyperf-Specific Quirks:

    • Container Binding: Macros on the container may conflict with Hyperf’s autowiring. Prefer explicit bindings.
    • Lifecycle Hooks: Macros don’t trigger Hyperf’s on() or after() hooks. Use them for direct method extensions only.
  4. Performance: Macros add minimal overhead, but avoid heavy computations in macro definitions (e.g., database queries). Cache results if needed.

Debugging

  • Macro Existence: Check if a macro is registered:
    if (MyService::hasMacro('log')) {
        // Macro exists.
    }
    
  • Macro Inspection: List all macros for a class:
    print_r(MyService::getMacros());
    
  • Hyperf Logs: Use \Hyperf\Logger\LoggerFactory to debug macro execution flow.

Extension Points

  1. Custom Macroable Traits: Extend the Macroable trait for domain-specific macros:

    trait MyMacroable {
        public static function macro($name, $macro) {
            static::macro($name, $macro);
        }
    }
    
  2. Global Macros: Register macros globally in a service provider:

    public function register()
    {
        \Hyperf\HttpServer\Request::macro('isApi', function () {
            return $this->header('Accept') === 'application/json';
        });
    }
    
  3. Macro Validation: Add validation to macros to ensure arguments are correct:

    MyService::macro('safeDivide', function ($dividend, $divisor) {
        if ($divisor === 0) {
            throw new \InvalidArgumentException('Divisor cannot be zero.');
        }
        return $dividend / $divisor;
    });
    
  4. Macro Namespacing: Use namespaces to avoid collisions in large applications:

    MyService::macro('Auth\validateToken', function ($token) { ... });
    
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.
aimeos/prisma
besmartand-pro/php-quality-config
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor
spatie/laravel-javascript-views