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

Di Laravel Package

bnf/di

Lightweight dependency injection container for PHP/Laravel projects. Configure bindings and resolve services automatically with simple, minimal setup—ideal for small apps or packages that need clean inversion of control without a heavy framework.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require bnf/di
    

    Add the container to your Laravel service provider (e.g., AppServiceProvider):

    use Bnf\Di\Container;
    
    public function register()
    {
        $this->app->singleton(Container::class, fn() => new Container());
    }
    
  2. Basic Usage Bind a class to an interface or concrete type:

    $container = app(Container::class);
    $container->bind(LoggerInterface::class, Logger::class);
    
  3. First Use Case Resolve a dependency in a controller or service:

    public function __construct(private LoggerInterface $logger)
    {
        // $logger is automatically resolved by the container
    }
    

Where to Look First

  • Documentation: Check the package’s README.md for basic binding/resolution syntax.
  • PSR-11 Compliance: Leverage familiar get() and has() methods.
  • Laravel Integration: Use app(Container::class) to access the container globally.

Implementation Patterns

Dependency Binding Strategies

  1. Singleton vs Transient

    • Use bind() for transient dependencies (new instance per resolution).
    • Use singleton() for shared instances (e.g., database connections, config services):
      $container->singleton(ConfigService::class, fn() => new ConfigService());
      
  2. Abstract Binding Bind interfaces to concrete implementations:

    $container->bind(RepositoryInterface::class, UserRepository::class);
    
  3. Contextual Binding Resolve dependencies conditionally (e.g., based on request data):

    $container->bindWhen(
        CacheDriver::class,
        fn($context) => $context['env'] === 'production' ? RedisDriver::class : FileDriver::class,
        ['env' => 'production']
    );
    

Workflows

  1. Service Layer Integration

    • Bind services in a dedicated ServiceProvider:
      public function register()
      {
          $this->app->make(Container::class)->bind(
              PaymentGateway::class,
              StripeGateway::class
          );
      }
      
  2. Middleware/Events Resolve dependencies in closures:

    $container->call([$this->mailer, 'send'], ['user@example.com']);
    
  3. Testing Override bindings in tests:

    $container->bind(MockLogger::class, MockLogger::class);
    $this->app->instance(LoggerInterface::class, new MockLogger());
    

Integration Tips

  • Laravel’s Service Container: Use bnf/di alongside Laravel’s container for hybrid setups:
    $this->app->extend(Container::class, fn($c) => new Container($c));
    
  • Autowiring: Combine with Laravel’s autowiring for seamless resolution:
    // In config/app.php
    'providers' => [
        Bnf\Di\DiServiceProvider::class, // Hypothetical provider
    ];
    

Gotchas and Tips

Pitfalls

  1. Circular Dependencies

    • Avoid binding ClassA to ClassB and ClassB to ClassA. Use setters or constructor injection carefully.
    • Fix: Refactor to use interfaces or a third-party mediator.
  2. Overriding Laravel Bindings

    • Binding the same class twice may cause conflicts. Use replace() or rebind():
      $container->rebind(LoggerInterface::class, NewLogger::class);
      
  3. Singleton Scope Leaks

    • Singletons persist across requests. Clear them manually if needed:
      $container->forget(LoggerInterface::class);
      

Debugging

  1. Resolution Errors

    • Check bindings with:
      $container->bound(LoggerInterface::class); // bool
      $container->getBindings(); // array of all bindings
      
    • Use dump($container->get(LoggerInterface::class)) to inspect resolved instances.
  2. Lazy Loading

    • Bind closures for deferred initialization:
      $container->bind(HeavyService::class, fn() => new HeavyService(config('app.debug')));
      

Extension Points

  1. Custom Resolvers Extend the container with a resolver:

    $container->addResolver(fn($concrete) => new $concrete());
    
  2. Contextual Resolution Pass context to bindings (e.g., request data):

    $container->bindWhen(
        User::class,
        fn($context) => $context['id'] ? User::find($context['id']) : new User(),
        ['id' => 1]
    );
    
  3. Integration with Laravel Events Bind event listeners dynamically:

    $container->bind(Handler::class, fn() => new Handler(app('events')));
    

Config Quirks

  • No Default Config: Unlike Laravel, bnf/di has no built-in config file. Define bindings programmatically.
  • Immutable Bindings: Use rebind() instead of bind() to replace existing bindings safely.
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
codifyo/ts-generator-bundle
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