michael-rubel / laravel-enhanced-container
This package provides DX tweaks for Service Container in Laravel.
Fund package maintenance!
paypal.com/donate/?hosted_button_id=KHLEL8PFS4AXJ
Installs: 58 923
Dependents: 3
Suggesters: 0
Security: 0
Stars: 87
Watchers: 5
Forks: 3
Open Issues: 0
Requires
- php: ^8.3|^8.4
- illuminate/contracts: ^11.21
- spatie/laravel-package-tools: ^1.9
Requires (Dev)
- brianium/paratest: ^7.4
- infection/infection: ^0.27.3
- laravel/pint: ^1.0
- nunomaduro/collision: ^8.0
- nunomaduro/larastan: ^2.0
- orchestra/testbench: ^9.3
- phpunit/phpunit: ^10.5
- dev-main
- 13.0.3
- 13.0.2
- 13.0.1
- 13.0.0
- 12.0.0
- 11.0.1
- 11.0.0
- 10.x-dev
- 10.0.3
- 10.0.2
- 10.0.1
- 10.0.0
- 9.x-dev
- 9.3.0
- 9.2.2
- 9.2.1
- 9.2.0
- 9.1.3
- 9.1.2
- 9.1.1
- 9.1.0
- 9.0.0
- 8.1.2
- 8.1.1
- 8.1.0
- 8.0.0
- 7.4.1
- 6.4.0
- dev-maintenance/address-+31
- dev-patch/up-to-laravel-11-33
- dev-php84
- dev-patch/laravel-11-21
- dev-patch/container-032024
This package is auto-updated.
Last update: 2024-12-04 19:27:31 UTC
README
Laravel Enhanced Container
This package provides additional features for Laravel's Service Container.
#StandWithUkraine
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.
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);
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, theInstanceInteractionException
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.
Testing
composer test
License
The MIT License (MIT). Please see License File for more information.