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

Laminas Di Laravel Package

laminas/laminas-di

Dependency injection container for Laminas apps. Supports autowiring, configuration-driven definitions, factories, and runtime instantiation to manage object creation and wiring with minimal boilerplate. Integrates with Laminas ServiceManager patterns and PSR-friendly practices.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require laminas/laminas-di
    

    Add to composer.json:

    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
    
  2. Basic Usage:

    use Laminas\Di\Di;
    use Laminas\Di\Injector;
    
    $injector = new Injector();
    $di = new Di($injector);
    
    // Resolve a class with constructor dependencies
    $service = $di->get('App\Service\MyService');
    
  3. First Use Case: Replace manual instantiation of a service with autowired dependencies:

    // Before (manual)
    $userRepository = new UserRepository(new DatabaseConnection());
    $userService = new UserService($userRepository);
    
    // After (autowired)
    $userService = $di->get(UserService::class);
    

Key Files to Explore


Implementation Patterns

Core Workflows

1. Autowiring Dependencies

// Service with constructor dependencies
class UserService {
    public function __construct(
        private UserRepository $repository,
        private LoggerInterface $logger
    ) {}
}

// Resolve via DI container
$service = $di->get(UserService::class);
  • Recursive Resolution: Laminas-DI resolves nested dependencies automatically.
  • Type Preferences: Configure via Injector::setTypePreference() to resolve interfaces vs. concrete classes.

2. Customizing Injection

// Override a dependency for a specific class
$injector->setService(UserRepository::class, new CustomUserRepository());
$service = $di->get(UserService::class); // Uses CustomUserRepository

// Pass arguments during creation
$service = $di->get(UserService::class, [
    'repository' => new CustomUserRepository(),
    'logger' => new NullLogger()
]);

3. Integration with Laravel

  • Service Provider Binding:
    use Laminas\Di\Injector;
    use Illuminate\Support\ServiceProvider;
    
    class AppServiceProvider extends ServiceProvider {
        public function register() {
            $injector = new Injector();
            $this->app->bind('laminas-di', function () use ($injector) {
                return new Di($injector);
            });
        }
    }
    
  • Resolving Services:
    $di = app('laminas-di');
    $service = $di->get(MyService::class);
    

4. Generating Factories for Laminas ServiceManager

use Laminas\Di\Generator\InjectorGenerator;

$generator = new InjectorGenerator();
$factoryCode = $generator->generate('App\Service\MyService');
file_put_contents('MyServiceFactory.php', $factoryCode);
  • Useful for migrating from Laminas-DI to Laminas ServiceManager.

Advanced Patterns

Conditional Injection

$injector->setService(
    UserService::class,
    function (Injector $injector) {
        return new UserService(
            $injector->get(UserRepository::class),
            config('app.debug') ? new DebugLogger() : new ProductionLogger()
        );
    }
);

Interface vs. Concrete Resolution

$injector->setTypePreference(LoggerInterface::class, MonologLogger::class);
$service = $di->get(UserService::class); // Uses MonologLogger

Performance Optimization

  • Cache Class Definitions:
    $injector->setClassDefinitionCache(new FilesystemCache('/path/to/cache'));
    
  • Preload Definitions:
    $injector->preloadDefinitions([UserService::class, UserRepository::class]);
    

Gotchas and Tips

Pitfalls

  1. No Shared Instances by Default

    • Laminas-DI creates new instances for every get() call. To share instances, use a wrapper like Laminas\ServiceManager or manually cache resolved objects.
    • Workaround:
      $sharedService = $di->get(UserService::class);
      $di->setService(UserService::class, $sharedService); // Force sharing
      
  2. No Setter/Property Injection

    • Only constructor injection is supported. Use factories or wrapper classes for other injection methods.
    • Example:
      $injector->setService(UserService::class, function (Injector $injector) {
          $service = new UserService();
          $service->setRepository($injector->get(UserRepository::class));
          return $service;
      });
      
  3. PHP 8+ Type System Quirks

    • Union Types: Resolved as the first matching type in the union.
      // Resolves to the first type in `int|string`
      public function __construct(private int|string $id) {}
      
    • Variadic Constructors: Not supported (throws RuntimeException).
  4. Circular Dependencies

    • Laminas-DI detects and throws CircularDependencyException. Break cycles by:
      • Using interfaces for dependencies.
      • Injecting dependencies via setters in factories.
  5. PSR-11 Compliance

    • While Di implements PSR\Container\ContainerInterface, it does not fully comply with PSR\Container\ContainerInterface::get() requirements (e.g., throws exceptions on missing services instead of returning null).
    • Tip: Use a wrapper like Laminas\ServiceManager for strict PSR-11 compliance.

Debugging Tips

  1. Enable Verbose Logging

    $injector->setDebug(true);
    $di->get(UserService::class); // Logs resolution steps
    
  2. Inspect Class Definitions

    $definition = $injector->getClassDefinition(UserService::class);
    print_r($definition->getParameters());
    
  3. Common Errors & Fixes

    Error Cause Solution
    ClassNotFoundException Missing class or namespace Check autoloading (composer dump-autoload).
    CircularDependencyException Circular dependency Refactor to break the cycle.
    InvalidArgumentException Unsupported type hint Use supported types (no variadic, etc.).
    RuntimeException Factory return type mismatch Ensure factory returns the expected type.

Extension Points

  1. Custom Parameter Resolvers

    $injector->addParameterResolver(function ($parameter, $classDefinition) {
        if ($parameter->getType() === 'config') {
            return config($parameter->getName());
        }
        return null;
    });
    
  2. Post-Resolution Callbacks

    $injector->addPostResolver(UserService::class, function ($instance) {
        $instance->initialize();
    });
    
  3. Integrate with Laravel Events

    use Illuminate\Support\Facades\Event;
    
    Event::listen('laminas-di.resolved', function ($service, $class) {
        logger()->debug("Resolved {$class}: " . get_class($service));
    });
    
  4. Generate Custom Factories Extend Laminas\Di\Generator\InjectorGenerator to create domain-specific factory logic.


Laravel-Specific Quirks

  1. Service Provider Binding

    • Bind the container to Laravel’s IoC:
      $this->app->singleton('laminas-di', function () {
          $injector = new Injector();
          $injector->setTypePreference(LoggerInterface::class, MonologLogger::class);
          return new Di($injector);
      });
      
  2. Conflict with Laravel’s Container

    • Avoid double-resolution issues:
      // Bad: Resolves via Laravel's container first, then Laminas-DI
      $di = app('laminas-di')->get(UserService::class);
      
      // Good: Use Laminas-DI exclusively for a namespace
      $di = app('laminas-di');
      $service = $di->get(UserService::class);
      
  3. Configuration Integration

    • Load Laminas-DI config from Laravel’s config/di.php:
      $injector = new Injector();
      $injector->configure(config
      
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
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