### Composer Installation Source: https://github.com/lucatume/di52/blob/master/README.md Install the DI52 library using Composer by running the following command in your project. ```bash composer require lucatume/di52 ``` -------------------------------- ### Service Registration via App (Service Locator) Source: https://github.com/lucatume/di52/blob/master/README.md A shorter example demonstrating service registration directly through the App class, which acts as a Service Locator and proxies calls to the underlying Container. ```php getDetails(); $this->container->singleton(LegacyClassOne::class, new LegacyClassOne($details)); $this->container->bind(LegacyInterfaceTwo::class, new LegacyClassTwo($details)); } } // Application bootstrap file use lucatume\DI52\Container; $container = new Container(); // The provider `register` method will not be called immediately... $container->register(ProviderOne::class); // ...it will be called here as it provides the binding of `LegacyClassOne` $legacyOne = $container->get(LegacyClassOne::class); // Will not be called again here, done already. $legacyTwo = $container->get(LegacyInterfaceTwo::class); ``` -------------------------------- ### Booting Service Providers with Conditional Bindings Source: https://github.com/lucatume/di52/blob/master/README.md Service providers can overload the `boot` method to perform registrations after initial setup, useful for conditional bindings based on constants or environment variables. The container's `boot` method triggers the `boot` method on all registered providers. ```php // file ProviderOne.php use lucatume\DI52\ServiceProvider; class ProviderOne extends ServiceProvider { public function register() { $this->container->bind(InterfaceOne::class, ClassOne::class); $this->container->bind(InterfaceTwo::class, ClassTwo::class); $this->container->singleton(InterfaceThree::class, ClassThree::class); } public function boot() { if(defined('SOME_CONSTANT')) { $this->container->bind(InterfaceFour::class, ClassFour::class); } else { $this->container->bind(InterfaceFour::class, AnotherClassFour::class); } } } // Application bootstrap file. use lucatume\DI52\Container; $container = new Container(); $container->register(ProviderOne::class); $container->register(ProviderTwo::class); $container->register(ProviderThree::class); // Some code later ... $container->boot(); ``` -------------------------------- ### Service Locator Usage Example Source: https://github.com/lucatume/di52/blob/master/README.md Demonstrates how to retrieve a service from a Service Locator. The Service Locator is typically a globally-available DI Container. ```php $database = $serviceLocator->get('database'); ``` -------------------------------- ### Dependency Resolution with Container Get Source: https://github.com/lucatume/di52/blob/master/README.md Illustrates how the DI Container's `get` method resolves and injects dependencies for a given class. It reads type-hinted dependencies from the constructor. ```php // file ClassThree.php class ClassThree { private $one; private $two; public function __construct(ClassOne $one, ClassTwo $two){ $this->one = $one; $this->two = $two; } } // The application bootstrap file use lucatume\DI52\Container; $container = new Container(); $three = $container->get('ClassThree'); ``` -------------------------------- ### Instantiating a class with interface dependencies Source: https://github.com/lucatume/di52/blob/master/README.md Shows how to instantiate class A by providing concrete implementations of BInterface and CInterface. ```php class B implements BInterface {} class C implements CInterface {} $a = new a(new B(), new C()); ``` -------------------------------- ### Basic Container Initialization Source: https://github.com/lucatume/di52/blob/master/README.md Include the Composer autoloader and create a new instance of the DI container to begin using it. ```php singleton(DbInterface::class, MySqlDb::class); ``` -------------------------------- ### Instantiating a class with concrete dependencies Source: https://github.com/lucatume/di52/blob/master/README.md Shows how to manually instantiate class A by providing instances of B and C to its constructor. ```php $a = new A(new B(), new C()); ``` -------------------------------- ### DI Container Initialization and Service Registration Source: https://github.com/lucatume/di52/blob/master/README.md Shows how to initialize a DI Container and make it globally available via the App class (acting as a Service Locator). Services are registered using singleton bindings. ```php singleton('database', MySqlDb::class); // We can now globally, i.e. anywhere in the code, access the `db` service. $db = App::get('database'); ``` -------------------------------- ### Application Entrypoint Source: https://github.com/lucatume/di52/blob/master/README.md The application entrypoint file (`index.php`) lazily resolves the dependency tree based on the bootstrap configuration. ```php serve(); ?> ?> ``` -------------------------------- ### Service Locator Initialization Source: https://github.com/lucatume/di52/blob/master/README.md Configure the DI container as a globally available Service Locator using the `lucatume\DI52\App` class. ```php singleton(DBDriverInterface::class, MYSqlDriver::class); $container->singleton(RepositoryInterface::class, MYSQLRepository::class); $container->get(RepositoryInterface::class); ``` -------------------------------- ### Service Provider with Primitive Injection Source: https://github.com/lucatume/di52/blob/master/README.md Demonstrates injecting primitive types into a service provider before registration using `when`, `needs`, and `give`. ```php // file ProviderOne.php use lucatume\DI52\ServiceProvider; class ProviderOne extends ServiceProvider { /** * @var bool */ protected $service_enabled; public function __construct(\lucatume\DI52\Container $container, $service_enabled) { parent::__construct($container); $this->service_enabled = $service_enabled; } public function register() { if (!$this->service_enabled) { return; } $this->container->bind(InterfaceOne::class, ClassOne::class); } } // Application bootstrap file. use lucatume\DI52\Container; $container = new Container(); $container->when(ProviderOne::class) ->needs('$service_enabled') ->give(true); $container->register(ProviderOne::class); ``` -------------------------------- ### Class constructor with concrete type-hinting Source: https://github.com/lucatume/di52/blob/master/README.md Demonstrates how to define class dependencies using concrete class type-hinting in the constructor. ```php class A { private $b; private $c; public function __construct(B $b, C $c){ $this->b = $b; $this->c = $c; } } ``` -------------------------------- ### Contextual Binding with Different Implementations Source: https://github.com/lucatume/di52/blob/master/README.md Demonstrates how to bind different implementations of an interface based on the requesting class. Useful when multiple classes require the same interface but need distinct underlying implementations. ```php use lucatume\DI52\Container; $container = new Container(); /* * By default any object requiring an implementation of the `CacheInterface` * should be given the same instance of `Array Cache` */ $container->singleton(CacheInterface::class, ArrayCache::class); $container->bind(DbCache::class, function($container){ $cache = $container->get(CacheInterface::class); $dbCache = new DbCache($cache); return $dbCache; }); /* * But when an implementation of the `CacheInterface` is requested by * `TransactionManager`, then it should be given an instance of `Array Cache`. */ $container->when(TransactionManager::class) ->needs(CacheInterface::class) ->give(DbCache::class); /* * We can also bind primitives where the container doesn't know how to auto-wire * them. */ $container->when(MysqlOrm:class) ->needs('$dbUrl') ->give('mysql://user:password@127.0.0.1:3306/app'); /* * When primitives are bound to a class the container will correctly resolve them when building the class * bound to an interface. */ $container->bind(ORMInterface::class, MysqlOrm::class); // The `ORMInterface` will be resolved an instance of the `MysqlOrm` class, with the `$dbUrl` argument set correctly. $orm = $container->get(ORMInterface::class); ``` -------------------------------- ### Binding Implementations to Classes and Closures Source: https://github.com/lucatume/di52/blob/master/README.md Demonstrates binding interfaces to class names, closures, constructor arguments, factory methods, and pre-instantiated objects. Use 'bind' for new instances on each request. ```php use lucatume\DI52\Container; $container = new Container(); // Bind to a class name. $container->bind(AInterface::class, A::class); // Bind to a Closure. $container->bind(BInterface::class, function(){ return new BetterB(); }); // Bind to a constructor and methods that should be called on the built object. $container->bind(CInterface::class, LegacyC::class, ['init','register']); // Bind to a factory method. $container->bind(D::interface, [DFactory::class,'buildInstance']) // Bind to an object, it will be a singleton by default. $container->bind(E::interface, new EImplementation()); $e = $container->get(F::class); ``` -------------------------------- ### Class constructor with interface type-hinting Source: https://github.com/lucatume/di52/blob/master/README.md Demonstrates defining class dependencies using interface type-hinting in the constructor. ```php class A { private $b; private $c; public function __construct(BInterface $b, CInterface $c){ $this->b = $b; $this->c = $c; } } ``` -------------------------------- ### Storing and Retrieving Variables with Container Source: https://github.com/lucatume/di52/blob/master/README.md Demonstrates the basic usage of the DI Container for storing and retrieving simple variables using `setVar` and `getVar` methods. ```php use lucatume\DI52\Container; $container = new Container(); $container->setVar('number', 23); $number = $container->getVar('number'); ``` -------------------------------- ### Service Provider with Constructor Injection Source: https://github.com/lucatume/di52/blob/master/README.md Shows how to inject dependencies into a service provider's constructor. Remember to call the parent constructor. ```php // file ProviderOne.php use lucatume\DI52\ServiceProvider; class ProviderOne extends ServiceProvider { /** * @var ConfigHelper */ protected $config; public function __construct(\lucatume\DI52\Container $container, ConfigHelper $config) { parent::__construct($container); $this->config = $config; } public function register() { $this->container->when(ClassFour::class) ->needs('$value') ->give($this->config->get('value')); } } // Application bootstrap file. use lucatume\DI52\Container; $container = new Container(); $container->register(ProviderOne::class); ``` -------------------------------- ### Application Bootstrap Configuration Source: https://github.com/lucatume/di52/blob/master/README.md Defines how components are assembled in the application bootstrap file. It configures the DI container with singletons, bindings, and conditional bindings for specific classes. ```php singleton( TemplateInterface::class, static function () { return new PlainPHPTemplate(__DIR__ . '/templates'); } ); // The default application Repository is the Posts one. // When a class needs an instance of the `RepositoryInterface`, then // return an instance of the `PostsRepository` class. $container->bind(RepositoryInterface::class, PostsRepository::class); // But the Users page should use the Users repository. $container->when(UsersPageRequest::class) ->needs(RepositoryInterface::class) ->give(UsersRepository::class); // Bind primitive values, e.g. public function __construct( int $per_page ) {} $container->when(UsersPageRequest::class) ->needs('$per_page') ->give(10); // Fetch the above class without any further definitions $container->get(UsersPageRequest::class) // The `UsersRepository` will require a `DbConnection` instance, that // should be built at most once (singleton). $container->singleton(DbConnection::class); // Set the routes. $container->bind('home', HomePageRequest::class); $container->bind('users', UsersPageRequest::class); // Make the container globally available as a service locator using the App. App::setContainer($container); ``` -------------------------------- ### Class constructor with extended concrete type-hinting Source: https://github.com/lucatume/di52/blob/master/README.md Illustrates dependency injection using classes that extend the hinted concrete types. ```php class ExtendedB extends B {} class ExtendedC extends C {} $a = new a(new ExtendedB(), new ExtendedC()); ``` -------------------------------- ### Updating dependency instantiation after implementation change Source: https://github.com/lucatume/di52/blob/master/README.md Illustrates the manual code changes required when a dependency's implementation is updated. ```php // before $a = new A(new B(), new C()); //after $a = new A(new BetterB(), new C()); ``` -------------------------------- ### Resolving Concrete Class with Contextual Bindings Source: https://github.com/lucatume/di52/blob/master/CHANGELOG.md Demonstrates how to correctly resolve a concrete class when it has contextual bindings, ensuring proper dependency injection. ```php $container = new \lucatume\DI52\Container(); $container->bind(SomeInterface::class, SomeClass::class); $container->when(Someclass:class) ->needs('$num') ->give(20); // This now works, properly resolving SomeClass::class. $instance = $container->get(SomeInterface::class); ``` -------------------------------- ### Managing nested dependencies manually Source: https://github.com/lucatume/di52/blob/master/README.md Shows a scenario with multiple nested dependencies (E depends on D, D depends on A and C, A depends on B and C) and the manual instantiation required. ```php class D implements DInterface{ public function __construct(AInterface $a, CInterface $c){} } class E { public function __construct(DInterface $d){} } $a = new A (new BetterB(), new C()); $d = new D($a, $c); $e = new E($d); ``` -------------------------------- ### Binding Implementations Using ArrayAccess API Source: https://github.com/lucatume/di52/blob/master/README.md Shows how to use the ArrayAccess API for storing variables and binding implementations, similar to Pimple. Bound closures receive the container instance. ```php use lucatume\DI52\Container; $container = new Container(); // Storing vars using the ArrayAccess API. $container['db.name'] = 'appDb'; $container['db.user'] = 'root'; $container['db.pass'] = 'secret'; $container['db.host'] = 'localhost:3306'; // Bindings can be set using ArrayAccess methods. $container['db.driver'] = MYSQLDriver::class; // Bound closures will receive the container instance as argument. $container['db.connection'] = function($container){ $host = $container['db.host'] $user = $container['db.user'], $pass = $container['db.pass'], $name = $container['db.name'], $dbDriver = $container['db.driver']; $dbDriver->connect($host, $user, $pass, $name); return new DBConnection($dbDriver); }; // Equivalent to $container->get('db.connection'); $dbConnection = $container['db.connection']; // Using ArrayAccess API to store a closure as a variable. $container['uniqid'] = $container->protect(function(){ return uniqid('id', true); }); ``` -------------------------------- ### Registering Service Providers for Organized Bindings Source: https://github.com/lucatume/di52/blob/master/README.md Service providers extend `lucatume\DI52\ServiceProvider` to organize binding registrations into logical units. Register providers using the container's `register` method. ```php use lucatume\DI52\ServiceProvider; // file ProviderOne.php class ProviderOne extends ServiceProvider { public function register() { $this->container->bind(InterfaceOne::class, ClassOne::class); $this->container->bind(InterfaceTwo::class, ClassTwo::class); $this->container->singleton(InterfaceThree::class, ClassThree::class); } } // Application bootstrap file. use lucatume\DI52\Container; $container = new Container(); $container->register(ProviderOne::class); $container->register(ProviderTwo::class); $container->register(ProviderThree::class); $container->register(ProviderFour::class); ``` -------------------------------- ### Container Unbound Class Resolution Modes Source: https://github.com/lucatume/di52/blob/master/README.md Illustrates how to control the resolution mode (prototype vs. singleton) for unbound classes when creating a DI52 container. ```php use lucatume\DI52\Container; $container1 = new Container(); $container2 = new Container(true); // Default resolution of unbound classes is prototype. assert($container1->get(A::class) !== $container1->get(A::class)); // The second container will resolve unbound classes once, then store them as singletons. assert($container2->get(A::class) === $container2->get(A::class)); ``` -------------------------------- ### Set up aliases for non-PSR namespaced classes Source: https://github.com/lucatume/di52/blob/master/README.md If using tad_DI52_Container and tad_DI52_ServiceProvider, add this code to your bootstrap file to maintain compatibility after removing aliases.php in version 3.3.0. ```php bind(RepositoryInterface::class, PostRepository::class); $container->bind(CacheInterface::class, ArrayCache::class); $container->bind(LoggerInterface::class, FileLogger::class); // Decorators are built left to right, outer decorators are listed first. $container->bindDecorators(PostEndpoint::class, [ LoggingEndpoint::class, CachingEndpoint::class, BaseEndpoint::class ], ['register'], true); ``` -------------------------------- ### Using Callbacks for Lazy Instantiation Source: https://github.com/lucatume/di52/blob/master/README.md The `Container::callback` method allows you to defer the instantiation of a class until its method is actually called. This avoids eager instantiation when a dependency might not be used. The container returns the same callback for singletons. ```php use lucatume\DI52\Container; $container = new Container(); add_filter('some_filter', [$container->get(SomeFilteringClass::class), 'filter']); ``` ```php use lucatume\DI52\Container; $container = new Container(); $container->singleton(SomeFilteringClass::class); add_filter('some_filter', $container->callback(SomeFilteringClass::class, 'filter')); ``` ```php // Some code later we need to remove the filter: we'll get the same callback. remove_filter('some_filter', App::callback(SomeFilteringClass::class, 'filter')); ``` -------------------------------- ### Tagging Implementations for Group Referencing Source: https://github.com/lucatume/di52/blob/master/README.md Use the `tag` method to group similar implementations. This is useful when the same method needs to be called on multiple bound objects. The `tagged` method retrieves all implementations associated with a specific tag. ```php use lucatume\DI52\Container; $container = new Container(); $container->bind(UnsupportedEndpoint::class, function($container){ $template = '404'; $message = 'Nope'; $redirectAfter = 3; $redirectTo = $container->get(HomeEndpoint::class); return new UnsupportedEndpoint($template, $message, $redirectAfter, $redirectTo); }); $container->tag([ HomeEndpoint::class, PostEndpoint::class, UnsupportedEndpoint::class, ], 'endpoints'); foreach($container->tagged('endpoints') as $endpoint) { $endpoint->register(); } ``` -------------------------------- ### Protecting Callables in the Container Source: https://github.com/lucatume/di52/blob/master/README.md Shows how to use the `protect` method to store a callable in the container without executing it immediately. This is useful for deferred execution or factory patterns. ```php $container = new tad_DI52_Container(); $container->setVar('randomNumberGenerator', $container->protect(function($val){ return mt_rand(1,100) + 23; })); $randomNumberGenerator = $container->getVar('randomNumberGenerator'); ``` -------------------------------- ### Configure Exception Masking in DI52 Container Source: https://github.com/lucatume/di52/blob/master/README.md Demonstrates how to set different exception masking behaviors for the DI52 container. Use `EXCEPTION_MASK_NONE` to disable masking, `EXCEPTION_MASK_MESSAGE` to modify the message, `EXCEPTION_MASK_FILE_LINE` to modify trace information, or combine them for default behavior. ```php use lucatume\DI52\Container; $container = new Container(); // The container will throw any exception thrown during a service resolution without any modification. $container->setExceptionMask(Container::EXCEPTION_MASK_NONE); // Wrap any exception thrown during a service resolution in a `ContainerException` instance, modify the message. $container->setExceptionMask(Container::EXCEPTION_MASK_MESSAGE); // Wrap any exception thrown during a service resolution in a `ContainerException` instance, modify the trace file and line. $container->setExceptionMask(Container::EXCEPTION_MASK_FILE_LINE); // You can combine the options, this is the default value. $container->setExceptionMask(Container::EXCEPTION_MASK_MESSAGE | Container::EXCEPTION_MASK_FILE_LINE); ``` -------------------------------- ### Binding Decorator Chain with After-Build Methods Source: https://github.com/lucatume/di52/blob/master/README.md Binds a decorator chain and specifies methods to be called after the chain is built. By default, these methods are only called on the base instance (the rightmost decorator). ```php use lucatume\DI52\Container; $container = new Container(); $container->bind(RepositoryInterface::class, PostRepository::class); $container->bind(CacheInterface::class, ArrayCache::class); $container->bind(LoggerInterface::class, FileLogger::class); // Decorators are built left to right, outer decorators are listed first. $container->bindDecorators(PostEndpoint::class, [ LoggingEndpoint::class, CachingEndpoint::class, BaseEndpoint::class ], ['register']); ``` -------------------------------- ### Binding a Decorator Chain Source: https://github.com/lucatume/di52/blob/master/README.md Binds a chain of decorators to an interface. Decorators are built from left to right, with outer decorators listed first. This allows extending functionality without subclassing. ```php use lucatume\DI52\Container; $container = new Container(); $container->bind(RepositoryInterface::class, PostRepository::class); $container->bind(CacheInterface::class, ArrayCache::class); $container->bind(LoggerInterface::class, FileLogger::class); // Decorators are built left to right, outer decorators are listed first. $container->bindDecorators(PostEndpoint::class, [ LoggingEndpoint::class, CachingEndpoint::class, BaseEndpoint::class ]); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.