Container Introduction
DomainFlow provides a lightweight but feature-rich dependency injection container. This container can be the core of how services and dependencies are managed throughout your application.
Below is a detailed guide to help you understand and use it effectively.
Purpose and Features
- PSR-11 Compliant: You can use standard methods
get()
andhas()
to interact with container entries. - ArrayAccess Compatibility: Interact with the container via
['key']
syntax if preferred. - Automatic Binding and Resolution: Use
bind()
,singleton()
, orinstance()
to register dependencies, andmake()
orget()
to resolve them. - Reflection-Based Autowiring: Optionally, the container can inspect your classes' constructors, typed parameters, and
#[Inject]
attributes to automatically resolve dependencies without verbose manual binding. - Contextual Binding: Override which concrete class is injected into specific classes (or contexts).
- Tagging: Group services under tags for bulk retrieval or iteration.
- Scopes: Create sub-containers (scopes) that inherit from a parent container but maintain their own overrides.
Installation
If you're using the container in a standalone project, you can install it via Composer:
composer require domainflow/container
Basic Usage
When you start working with the container, the typical steps are:
- Instantiate the
Container
. - Bind your classes or closures to the container.
- Resolve them as needed via
make()
orget()
.
The following sections demonstrate a few real-world usage patterns.
Example: container_basic_binding_a.php
<?php declare(strict_types=1);
use DomainFlow\Container;
// 1. Instantiate the container
$container = new Container();
// 2. Bind using a closure
$container->bind('logger', function () {
// Suppose Logger is a custom class
return new Logger('/var/log/app.log');
});
// 3. Resolve the logger via `make` or `get`
$logger = $container->make('logger');
$logger->info("Hello from the container!");
Note: You need to create a class named Logger
for this example to work or use an existing class from your project.
Summary
The Container is a foundational building block, letting you register and retrieve services in a straightforward manner. It supports a range of patterns — from the simplest closure factory to advanced reflection-based autowiring, contextual overrides, tagging, and scoping.
As you continue through the documentation, you’ll learn how to leverage these features to cleanly manage dependencies in your application code.