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

Dependency Injection Laravel Package

symfony/dependency-injection

Symfony DependencyInjection standardizes and centralizes object construction with a powerful service container. Define services and parameters, manage autowiring and configuration, and optimize performance through compilation for cleaner, decoupled apps.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require symfony/dependency-injection
    

    Laravel already includes this package as part of its core, so no additional installation is needed.

  2. First Use Case:

    • Understanding the Container: Laravel’s Service Container (powered by Symfony’s DependencyInjection) is the central place for managing class dependencies and service instantiation.
    • Basic Injection:
      // In a service class
      public function __construct(private MyDependency $dependency) {}
      
      // Laravel will automatically inject `MyDependency` if it's registered.
      
  3. Where to Look First:

    • Laravel’s Service Container: Illuminate\Container\Container (extends Symfony\Component\DependencyInjection\ContainerInterface).
    • Configuration: Laravel’s config/app.php defines service bindings and providers.
    • Documentation: Symfony DependencyInjection and Laravel Container.

Implementation Patterns

Core Workflows

  1. Service Binding and Resolution:

    • Manual Binding:
      $container->bind('MyService', function ($container) {
          return new MyService($container->make('AnotherService'));
      });
      
    • Automatic Binding (Autowiring): Enable in config/app.php:
      'providers' => [
          Illuminate\Foundation\ProviderRepository::class,
      ],
      'aliases' => [],
      'bindings' => [],
      'singletons' => [],
      'whenLoadingConfig' => [],
      'autowire' => true, // Enable autowiring
      'apiResources' => [],
      'except' => [],
      'caching' => false,
      'terminate' => [],
      'namespace' => 'App\\',
      
  2. Tagging and Collecting Services:

    • Tag services in a provider’s register method:
      $this->app->tag(['firstService', 'secondService'], 'my.tag');
      
    • Retrieve tagged services:
      $services = $this->app->tagged('my.tag');
      
  3. Lazy Loading and Proxies:

    • Use lazy() to defer instantiation:
      $container->bind('LazyService', function () {
          return new LazyService();
      })->setLazy(true);
      
    • Laravel’s singleton() method also supports lazy loading.
  4. Context and Scopes:

    • Bind services to specific scopes (e.g., Illuminate\Contracts\Container\ScopedBinding):
      $container->bind('ScopedService', ScopedService::class)->in('scoped');
      
  5. Parameter Bag:

    • Configure application-wide parameters in config/app.php or environment files:
      $container->setParameter('app.name', 'MyApp');
      
    • Access parameters:
      $name = $container->getParameter('app.name');
      
  6. Extension and Compilation:

    • Extend the container with custom logic via Service Providers:
      public function register()
      {
          $this->app->singleton('MyService', function ($app) {
              return new MyService($app->make('AnotherService'));
          });
      }
      
  7. Attribute-Based Configuration:

    • Use attributes like #[Target] to configure services:
      use Symfony\Component\DependencyInjection\Attribute\Target;
      
      class MyService {
          #[Target('app.name')]
          public function setName(string $name) {}
      }
      

Gotchas and Tips

Pitfalls

  1. Circular Dependencies:

    • Laravel’s container will throw an exception if circular dependencies are detected. Refactor to break the cycle or use lazy loading.
  2. Service Overwriting:

    • Binding a service twice (e.g., bind() followed by singleton()) will overwrite the previous binding. Use extend() to modify existing bindings without replacing them.
  3. Lazy Loading Quirks:

    • Lazy services are instantiated only when first used. Be cautious with lazy services in constructors or early initialization.
  4. Tagged Services and Priorities:

    • Tagged services are collected in the order they are registered. Use PriorityTaggedServiceTrait or custom sorting if order matters:
      $services = $this->app->tagged('my.tag')->sort(function ($a, $b) {
          return strcmp($a['priority'], $b['priority']);
      });
      
  5. Environment Variables in Config:

    • Avoid referencing environment variables directly in service definitions. Use Laravel’s env() helper or bind them as parameters:
      $container->setParameter('app.debug', env('APP_DEBUG', false));
      
  6. Deprecated Features:

    • Some Symfony DI features (e.g., PhpDumper) may not work as expected in Laravel’s context. Prefer Laravel’s native solutions (e.g., php artisan optimize).
  7. Type Safety:

    • Laravel’s container is not strictly typed by default. Use PHP 8’s type hints and #[AutowireCallable] for stricter control:
      #[AutowireCallable]
      public function __construct(private MyService $service) {}
      

Debugging Tips

  1. Dump Container Contents:

    • Use php artisan container:dump (custom command) or inspect the container manually:
      dd($this->app->getBindings());
      
  2. Check for Missing Bindings:

    • Enable debug mode (APP_DEBUG=true) to get detailed errors for unresolved dependencies.
  3. Service Existence:

    • Verify if a service is bound before resolving:
      if ($this->app->bound('MyService')) {
          $service = $this->app->make('MyService');
      }
      
  4. Parameter Validation:

    • Validate parameters early in the register method of service providers to catch misconfigurations.

Extension Points

  1. Custom Compilers:

    • Extend Laravel’s container compilation by creating a custom Compiler pass:
      $this->app->resolving('MyService', function ($service, $app) {
          // Post-resolution logic
      });
      
  2. Dynamic Bindings:

    • Use closures for dynamic service creation:
      $this->app->bind('DynamicService', function ($app) {
          return new DynamicService($app['config']['dynamic.value']);
      });
      
  3. Interface Binding:

    • Bind interfaces to implementations for loose coupling:
      $this->app->bind(
          Illuminate\Contracts\Auth\Authenticatable::class,
          App\Models\User::class
      );
      
  4. Event Listeners:

    • Attach listeners to container events (e.g., Illuminate\Container\Events\BindingResolved):
      $this->app->resolved('MyService', function ($service) {
          // Logic after service resolution
      });
      
  5. Custom Container:

    • Extend Laravel’s container by creating a custom class that extends Illuminate\Container\Container and override methods like make() or bind().
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.
calmfox/watch-sylius
damienfern/grpc-symfony-bundle
atoolo/index-bundle
atoolo/genai-bundle
coprotoai/laravel-ticket
davidjln/llm-carbon-bundle
cryonighter/valid-request-bundle
coolms/taxonomy-bundle
coolms/field-bundle
articulate-orm/symfony
aaix/laravel-tall-architect
ephoto/akeneo-connector
emmanuelballery/eb-plantumlbundle
emielburgman/symfony-visitor-beacon
emielburgman/symfony-visit-storage
emielburgman/symfony-security-headers
emielburgman/symfony-log-viewer
emarref/xdebug-bundle
emarref/pubnub-bundle
elriseio/finance-money-bundle