Skip to main content

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() and has() to interact with container entries.
  • ArrayAccess Compatibility: Interact with the container via ['key'] syntax if preferred.
  • Automatic Binding and Resolution: Use bind(), singleton(), or instance() to register dependencies, and make() or get() 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:

  1. Instantiate the Container.
  2. Bind your classes or closures to the container.
  3. Resolve them as needed via make() or get().

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.