Skip to content

wilaak/pico-di

Repository files navigation

PicoDI

Ridiculously simple dependency injection (DI) container for PHP.

Overview

  • All services are singletons; each dependency is instantiated only once and shared (lazy-loading).
  • Extremely lightweight: just 86 lines of code.
  • Supports automatic constructor injection using type hints (autowiring).
  • Fully compatible with the PSR-11 container interface.

What is a DI container?

A dependency injection container is a tool that automatically creates and manages the objects your application needs, wiring their dependencies together for you. It centralizes how services are configured and connected, making your code easier to maintain, test, and extend.

Without a container:

// You must manually create and pass every dependency, everywhere you need them.$logger = newFileLogger('/tmp/app.log'); $mailer = newMailer($logger); $userService = newUserService($logger, $mailer); $orderService = newOrderService($logger, $mailer); // If you need these services in other places, you have to repeat this process.// If you want to swap the logger implementation, you must update every place it's used.// Adding a new dependency or changing the wiring means editing code in many places.

With a container:

// Configure how your objects should be instantiated.$config = [ LoggerInterface::class => FileLogger::class, FileLogger::class => function(){returnnewFileLogger('/tmp/app.log')} Mailer::class => function(ServiceContainer$container){returnnewMailer($container->get(LoggerInterface::class))} ]; $container = newServiceContainer($config); // The container will automatically inspect the constructor and inject its dependencies.$userService = $container->get(UserService::class); $orderService = $container->get(OrderService::class); // If you want to swap the logger implementation, just change the config in one place!

Installation

Install using composer:

composer require wilaak/picodi

Requires PHP 8.0 or above

Usage example

Here's a basic usage example.

useWilaak\PicoDI\ServiceContainer; interface LoggerInterface{publicfunctionlog(string$message): void} class FileLogger implements LoggerInterface{publicfunction__construct(privatestring$file){} publicfunctionlog(string$message): void{file_put_contents($this->file, $message . PHP_EOL, FILE_APPEND)} } class UserService{publicfunction__construct(privateLoggerInterface$logger){} publicfunctioncreateUser(string$username): void{$this->logger->log("Created user: $username")} } $config = [ LoggerInterface::class => FileLogger::class, FileLogger::class => function(ServiceContainer$container){// You can use $container->get to resolve other dependencies if needed// For this example, we just instantiate FileLogger directlyreturnnewFileLogger('/tmp/app.log')} ]; $container = newServiceContainer($config); $userService = $container->get(UserService::class); $userService->createUser('alice');

Configuration

The configuration array specifies how the container resolves dependencies. The following key value types are supported:

String (Alias)

Defines an alias for the class or interface specified in the key. You can use either the class name resolution operator or plain strings, but the ::class syntax is preferred for readability and IDE support.

$config = [ LoggerInterface::class => FileLogger::class, ];

Callable (Factory Function)

Use a callable (e.g anonymous functions) to explicitly return the desired value.

$config = [ LoggerInterface::class => function(ServiceContainer$container){$logger = newFileLogger(file: '/var/log/app.log'); // Optionally, inject other services from the container if needed:// $dependency = $container->get(OtherService::class);return$logger}, ];

Credits

This container is based on the one from the article A Stupidly Simple PHP Dependency Injection Container from Evan Hildreth.

About

Ridiculously simple dependency injection (DI) container for PHP

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages