michael-rubel/laravel-enhanced-container

This package provides DX tweaks for Service Container in Laravel.
115,771 88
Install
composer require michael-rubel/laravel-enhanced-container
Latest Version:13.0.3
PHP:^8.3|^8.4
License:MIT
Last Updated:Dec 4, 2024
Links: GitHub  ·  Packagist
Maintainer: michael-rubel

Method binding with Service Container   Call Proxy

Laravel Enhanced Container

Latest Version on Packagist Total Downloads Code Quality Code Coverage GitHub Tests Action Status PHPStan

This package provides additional features for Laravel's Service Container.

#StandWithUkraine

SWUbanner

Contents

Installation

Install the package via composer (Laravel 11):

composer require michael-rubel/laravel-enhanced-container

If you need the package for older versions of Laravel, check changelog.

Usage

Resolve contextual binding outside of constructor

call(ServiceInterface::class, context: static::class);

// The `call` method automatically resolves the implementation from the interface you passed.
// If you pass the context, the proxy tries to resolve contextual binding instead of global binding first.

🔝 back to contents

Method binding

This feature makes it possible to override the behavior of methods accessed using the call.

Assuming that is your function in the service class:

class Service
{
    public function yourMethod(int $count): int
    {
        return $count;
    }
}

Bind the service to an interface:

$this->app->bind(ServiceInterface::class, Service::class);

Call your service method through container:

call(ServiceInterface::class)->yourMethod(100);

For example in feature tests:

$this->app->bind(ApiGatewayContract::class, InternalApiGateway::class);

bind(ApiGatewayContract::class)->method('performRequest', function ($service, $app, $params) {
    // Note: you can access `$params` passed to the method call.

    return true;
});

$apiGateway = call(ApiGatewayContract::class);
$request = $apiGateway->performRequest();
$this->assertTrue($request);

Note: if you rely on interfaces, the proxy will automatically resolve bound implementation for you.

Note for package creators

If you want to use method binding in your own package, you need to make sure the LecServiceProvider registered before you use this feature.

$this->app->register(LecServiceProvider::class);

🔝 back to contents

Method forwarding

This feature automatically forwards the method if it doesn't exist in your class to the second one defined in the forwarding configuration.

You can define forwarding in your ServiceProvider:

use MichaelRubel\EnhancedContainer\Core\Forwarding;

Forwarding::enable()
    ->from(Service::class)
    ->to(Repository::class);

You can as well use chained forwarding:

Forwarding::enable()
    ->from(Service::class)
    ->to(Repository::class)
    ->from(Repository::class)
    ->to(Model::class);
Important notes
  • Pay attention to which internal instance you're now working on in CallProxy when using forwarding. The instance may change without your awareness. If you interact with the same methods/properties on a different instance, the InstanceInteractionException will be thrown.
  • If you use PHPStan/Larastan you'll need to add the @method docblock to the service to make it static-analyzable, otherwise it will return an error that the method doesn't exist in the class.

🔝 back to contents

Testing

composer test

License

The MIT License (MIT). Please see License File for more information.

Related Packages

michael-rubel/laravel-couponables

This package provides polymorphic coupon functionality for your Laravel applicat...

109,187 195
michael-rubel/laravel-formatters

This package is a collection of classes you can use to standardize data formats...

95,686 94
doctrine/dbal

Powerful PHP database abstraction layer (DBAL) with many features for database s...

637,827,751 9,703
laravel/framework

The Laravel Framework.

589,172,971 34,950
laravel/tinker

Powerful REPL for the Laravel framework.

498,216,183 7,442

Version History

Version Released PHP Laravel License
13.0.3 ^8.3|^8.4 ^11.21 MIT
13.0.2 ^8.3 ^11.21 MIT
13.0.1 ^8.3 ^11.21 MIT
13.0.0 ^8.3 ^11.21 MIT
12.0.0 ^8.1 ^10.0|^11.0 MIT