Weave 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

Fluent Laravel Package

respect/fluent

Respect/Fluent is a small PHP library for building fluent, chainable APIs and expressive method chains. It helps create readable domain-specific syntax and cleaner interfaces with minimal boilerplate, making object interactions more natural and easier to compose.

Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require respect/fluent
    

    No additional configuration is required—just autoload via Composer.

  2. First Use Case Create a fluent interface for a domain-specific namespace (e.g., App\Services\Payment):

    use Respect\Fluent\Fluent;
    
    $payment = Fluent::make('App\Services\Payment');
    $result = $payment->charge(100)->refund(50);
    

    This dynamically generates a fluent chain for App\Services\Payment::charge() and Payment::refund().

  3. Where to Look First

    • Source Code (if available) for edge cases.
    • Respect\Fluent\Fluent class docs (if generated via PHPDoc).
    • Laravel’s service container integration (see Implementation Patterns).

Implementation Patterns

Core Workflows

  1. Dynamic Method Chaining Use Fluent::make() to auto-generate fluent interfaces for any class:

    $user = Fluent::make('App\Models\User');
    $user->find(1)->update(['name' => 'Alice']);
    

    Maps to User::find(1)->update(...).

  2. Laravel Service Container Integration Bind fluent interfaces to the container for dependency injection:

    $this->app->bind('payment.fluent', function ($app) {
        return Fluent::make('App\Services\Payment');
    });
    

    Inject via constructor:

    public function __construct(public Fluent $payment) {}
    
  3. Static vs. Instance Methods

    • Static methods: Use Fluent::make('Class')->method().
    • Instance methods: Chain after instantiation:
      $payment = Fluent::make('App\Services\Payment')->new();
      $payment->charge(100)->refund(50);
      
  4. Customizing Fluent Behavior Extend Respect\Fluent\Fluent to add middleware or validation:

    class CustomFluent extends Fluent {
        public function __call($method, $args) {
            if ($method === 'charge' && $args[0] < 1) {
                throw new \InvalidArgumentException('Amount must be > 0');
            }
            return parent::__call($method, $args);
        }
    }
    

Integration Tips

  • Laravel Facades: Wrap Fluent in a facade for cleaner syntax:
    Facades\Fluent::make('App\Services\Payment')->charge(100);
    
  • API Clients: Ideal for REST clients (e.g., Stripe, Shopify):
    $stripe = Fluent::make('App\Services\StripeClient');
    $stripe->customers()->create(['email' => '[email protected]']);
    
  • Testing: Mock fluent interfaces with Mockery:
    $mock = Mockery::mock('overload:App\Services\Payment');
    $mock->shouldReceive('charge')->andReturnSelf();
    

Gotchas and Tips

Pitfalls

  1. Method Name Collisions Fluent assumes all methods are chainable. If a method returns non-self (e.g., User::getId()), it breaks the chain. Fix: Use ->then() to reset the chain:

    $user->find(1)->then()->update(['name' => 'Alice']);
    
  2. Static Method Limitations Fluent doesn’t natively support static methods with arguments beyond the first. Workaround: Use a wrapper class or closure:

    $payment = Fluent::make('App\Services\Payment');
    $payment->callStatic('setApiKey', ['sk_live_123']);
    
  3. Performance Overhead Dynamic method calls add reflection overhead. Tip: Cache Fluent instances in Laravel’s container or use a factory pattern for heavy usage.

  4. Namespace Ambiguity Avoid namespaces with similar prefixes (e.g., App\Services\Payment vs. App\Service\Payment). Fix: Use fully qualified names:

    Fluent::make('App\Services\PaymentService');
    

Debugging

  • Enable Reflection Errors Set error_reporting(E_ALL) to catch undefined method issues early.
  • Log Fluent Calls Override __call to log method chains for debugging:
    public function __call($method, $args) {
        \Log::debug("Fluent called: {$method} with args: " . json_encode($args));
        return parent::__call($method, $args);
    }
    

Extension Points

  1. Custom Callables Pass a closure to Fluent::make() for pre-processing:

    $fluent = Fluent::make('App\Services\Payment', function ($method, $args) {
        if ($method === 'charge') {
            $args[0] = $args[0] * 1.1; // Add 10% fee
        }
        return [$method, $args];
    });
    
  2. Middleware Pipeline Chain middleware to validate/modify calls:

    $fluent = Fluent::make('App\Services\Payment')
        ->pipe(function ($callable) {
            return function ($method, $args) {
                if ($method === 'refund') {
                    \Log::info("Refund initiated for {$args[0]}");
                }
                return $callable($method, $args);
            };
        });
    
  3. Fluent for Collections Combine with Laravel Collections for fluent-style data processing:

    $users = Fluent::make('App\Models\User')
        ->all()
        ->filter(fn ($user) => $user->active)
        ->pluck('name');
    
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.
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr
laravel2580/idehelpers
delatbabel/viewpages
anavel/gettext
muhamadrezaar/highcharts
delatbabel/keylists
frankkessler/salesforce-laravel-oauth2-rest
anavel/foundation
wdmtech/enviricons
eii/laravel-captcha
muka/shape-reader
tdt/json