PHPackages                             gacela-project/container - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [PSR &amp; Standards](/categories/psr-standards)
4. /
5. gacela-project/container

ActiveLibrary[PSR &amp; Standards](/categories/psr-standards)

gacela-project/container
========================

A minimalistic container dependency resolver

0.8.0(6mo ago)1175.2k↑1016.7%2MITPHPPHP &gt;=8.1CI passing

Since Apr 11Pushed 6mo ago1 watchersCompare

[ Source](https://github.com/gacela-project/container)[ Packagist](https://packagist.org/packages/gacela-project/container)[ Docs](https://gacela-project.com)[ Fund](https://chemaclass.com/sponsor)[ RSS](/packages/gacela-project-container/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (9)Dependencies (7)Versions (11)Used By (2)

Gacela Container
================

[](#gacela-container)

 [ ![GitHub Build Status](https://github.com/gacela-project/container/workflows/CI/badge.svg) ](https://github.com/gacela-project/container/actions) [ ![Scrutinizer Code Quality](https://camo.githubusercontent.com/fb2f7f0489256498d9835852e33eebf0efc2cc715905a68ca1d3d05feb9ff2b1/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f676163656c612d70726f6a6563742f636f6e7461696e65722f6261646765732f7175616c6974792d73636f72652e706e673f623d6d61696e) ](https://scrutinizer-ci.com/g/gacela-project/container/?branch=main) [ ![Scrutinizer Code Coverage](https://camo.githubusercontent.com/7e7f422a99b6fa8bb2c616b87d6d49698992e582afc3540750a44ad87c9bb493/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f676163656c612d70726f6a6563742f636f6e7461696e65722f6261646765732f636f7665726167652e706e673f623d6d61696e) ](https://scrutinizer-ci.com/g/gacela-project/container/?branch=main) [ ![Psalm Type-coverage Status](https://camo.githubusercontent.com/a6654b118fb31475cfbcaec921a40cddf3d14726de40add51cb04fbefd6de103/68747470733a2f2f73686570686572642e6465762f6769746875622f676163656c612d70726f6a6563742f636f6e7461696e65722f636f7665726167652e737667) ](https://shepherd.dev/github/gacela-project/container) [ ![MIT Software License](https://camo.githubusercontent.com/784362b26e4b3546254f1893e778ba64616e362bd6ac791991d2c9e880a3a64e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667) ](https://github.com/gacela-project/container/blob/master/LICENSE)

A minimalistic, PSR-11 compliant dependency injection container with automatic constructor injection and zero configuration.

Features
--------

[](#features)

- 🚀 **Zero Configuration**: Automatic constructor injection without verbose setup
- 🔄 **Circular Dependency Detection**: Clear error messages when dependencies form a loop
- 📦 **PSR-11 Compliant**: Standard container interface for interoperability
- ⚡ **Performance Optimized**: Built-in caching and warmup capabilities
- 🔍 **Introspection**: Debug and inspect container state easily
- 🎯 **Type Safe**: Requires type hints for reliable dependency resolution
- 🏷️ **PHP 8 Attributes**: Declarative configuration with #\[Inject\], #\[Singleton\], and #\[Factory\]

Installation
------------

[](#installation)

```
composer require gacela-project/container
```

Quick Start
-----------

[](#quick-start)

### Basic Usage

[](#basic-usage)

```
use Gacela\Container\Container;

// Simple auto-wiring
$container = new Container();
$instance = $container->get(YourClass::class);
```

### With Bindings

[](#with-bindings)

Map interfaces to concrete implementations:

```
$bindings = [
    LoggerInterface::class => FileLogger::class,
    CacheInterface::class => new RedisCache('localhost'),
    ConfigInterface::class => fn() => loadConfig(),
];

$container = new Container($bindings);
$logger = $container->get(LoggerInterface::class); // Returns FileLogger
```

### Contextual Bindings

[](#contextual-bindings)

Different implementations based on which class needs them:

```
// UserController gets FileLogger, AdminController gets DatabaseLogger
$container->when(UserController::class)
    ->needs(LoggerInterface::class)
    ->give(FileLogger::class);

$container->when(AdminController::class)
    ->needs(LoggerInterface::class)
    ->give(DatabaseLogger::class);

// Multiple classes can share the same contextual binding
$container->when([ServiceA::class, ServiceB::class])
    ->needs(CacheInterface::class)
    ->give(RedisCache::class);
```

### PHP 8 Attributes

[](#php-8-attributes)

Use attributes for declarative dependency configuration:

#### \#\[Inject\] - Specify Implementation

[](#inject---specify-implementation)

Override type hints to inject specific implementations:

```
use Gacela\Container\Attribute\Inject;

class NotificationService {
    public function __construct(
        #[Inject(EmailLogger::class)]
        private LoggerInterface $logger,
    ) {}
}

// EmailLogger will be injected even if LoggerInterface is bound to FileLogger
$service = $container->get(NotificationService::class);
```

#### \#\[Singleton\] - Single Instance

[](#singleton---single-instance)

Mark a class to be instantiated only once:

```
use Gacela\Container\Attribute\Singleton;

#[Singleton]
class DatabaseConnection {
    public function __construct(private string $dsn) {}
}

$conn1 = $container->get(DatabaseConnection::class);
$conn2 = $container->get(DatabaseConnection::class);
// $conn1 === $conn2 (same instance)
```

#### \#\[Factory\] - New Instances

[](#factory---new-instances)

Always create fresh instances:

```
use Gacela\Container\Attribute\Factory;

#[Factory]
class RequestContext {
    public function __construct(private LoggerInterface $logger) {}
}

$ctx1 = $container->get(RequestContext::class);
$ctx2 = $container->get(RequestContext::class);
// $ctx1 !== $ctx2 (different instances)
```

**Performance Note:** Attribute checks are cached internally, so repeated instantiations of the same class avoid expensive reflection operations, providing 15-20% performance improvement.

How It Works
------------

[](#how-it-works)

The container automatically resolves dependencies based on type hints:

- **Primitive types**: Uses default values (must be provided)
- **Classes**: Instantiates and resolves dependencies recursively
- **Interfaces**: Resolves using bindings defined in the container

### Example

[](#example)

```
class UserService {
    public function __construct(
        private UserRepository $repository,
        private LoggerInterface $logger,
    ) {}
}

class UserRepository {
    public function __construct(private PDO $pdo) {}
}

// Setup
$bindings = [
    LoggerInterface::class => FileLogger::class,
    PDO::class => new PDO('mysql:host=localhost;dbname=app', 'user', 'pass'),
];

$container = new Container($bindings);

// Auto-resolves UserService -> UserRepository -> PDO
$service = $container->get(UserService::class);
```

Advanced Features
-----------------

[](#advanced-features)

### Factory Services

[](#factory-services)

Create new instances on every call:

```
$factory = $container->factory(fn() => new TempFile());
$container->set('temp_file', $factory);

$file1 = $container->get('temp_file'); // New instance
$file2 = $container->get('temp_file'); // Different instance
```

### Extending Services

[](#extending-services)

Wrap or modify services (even before they're created):

```
$container->set('logger', fn() => new FileLogger('/var/log/app.log'));

$container->extend('logger', function ($logger, $container) {
    return new LoggerDecorator($logger);
});
```

### Protecting Closures

[](#protecting-closures)

Prevent closures from being executed:

```
$closure = fn() => 'Hello World';
$container->set('greeting', $container->protect($closure));

$result = $container->get('greeting'); // Returns the closure itself
```

### Resolving Callables

[](#resolving-callables)

Automatically inject dependencies into any callable:

```
$result = $container->resolve(function (LoggerInterface $logger, CacheInterface $cache) {
    $logger->info('Cache cleared');
    return $cache->clear();
});
```

### Service Introspection

[](#service-introspection)

Debug and inspect container state:

```
// Get all registered service IDs
$services = $container->getRegisteredServices();

// Check if service is a factory
if ($container->isFactory('temp_file')) {
    // Returns new instance each time
}

// Check if service is frozen (accessed)
if ($container->isFrozen('logger')) {
    // Cannot be modified anymore
}

// Get all bindings
$bindings = $container->getBindings();

// Get comprehensive statistics
$stats = $container->getStats();
/*
[
    'registered_services' => 42,
    'frozen_services' => 15,
    'factory_services' => 3,
    'bindings' => 8,
    'cached_dependencies' => 25,
    'memory_usage' => '2.34 MB'
]
*/
```

### Performance Optimization

[](#performance-optimization)

Pre-resolve dependencies for faster runtime:

```
// During application bootstrap
$container->warmUp([
    UserService::class,
    OrderService::class,
    PaymentProcessor::class,
]);

// Later requests benefit from cached dependency resolution
$service = $container->get(UserService::class); // Faster!
```

### Service Aliasing

[](#service-aliasing)

Create multiple names for the same service:

```
// Create an alias
$container->alias('db', PDO::class);

// Access via alias or original name
$db1 = $container->get('db');        // Same instance
$db2 = $container->get(PDO::class);  // Same instance

// Alias resolution is cached for optimal performance
```

API Reference
-------------

[](#api-reference)

### Container Methods

[](#container-methods)

MethodDescription`get(string $id): mixed`Retrieve or create a service`has(string $id): bool`Check if service exists`set(string $id, mixed $instance): void`Register a service`remove(string $id): void`Remove a service`resolve(callable $callable): mixed`Execute callable with dependency injection`factory(Closure $instance): Closure`Mark service as factory (new instance each time)`extend(string $id, Closure $instance): Closure`Wrap/modify a service`protect(Closure $instance): Closure`Prevent closure execution`getRegisteredServices(): array`Get all service IDs`isFactory(string $id): bool`Check if service is a factory`isFrozen(string $id): bool`Check if service is frozen`getBindings(): array`Get all bindings`warmUp(array $classNames): void`Pre-resolve dependencies`alias(string $alias, string $id): void`Create an alias for a service (with caching)`getStats(): array`Get container statistics for debugging and performance monitoring`when(string|array $concrete): ContextualBindingBuilder`Define contextual bindings for specific classes### Static Methods

[](#static-methods)

```
// Quick instantiation without container setup
$instance = Container::create(YourClass::class);
```

Best Practices
--------------

[](#best-practices)

### 1. Use Constructor Injection

[](#1-use-constructor-injection)

```
// Good
class UserController {
    public function __construct(
        private UserService $userService,
        private LoggerInterface $logger
    ) {}
}

// Avoid setter injection (not supported)
```

### 2. Always Use Type Hints

[](#2-always-use-type-hints)

```
// Good - type hint required
public function __construct(LoggerInterface $logger) {}

// Bad - will throw exception
public function __construct($logger) {}
```

### 3. Provide Default Values for Scalars

[](#3-provide-default-values-for-scalars)

```
// Good
public function __construct(
    UserRepository $repo,
    int $maxRetries = 3,
    string $env = 'production'
) {}

// Bad - scalars without defaults cannot be resolved
public function __construct(string $apiKey) {} // Exception!
```

### 4. Use Bindings for Interfaces

[](#4-use-bindings-for-interfaces)

```
// Always bind interfaces to implementations
$bindings = [
    LoggerInterface::class => FileLogger::class,
    CacheInterface::class => RedisCache::class,
];
```

### 5. Warm Up in Production

[](#5-warm-up-in-production)

```
// In your bootstrap file
$container->warmUp([
    // List frequently used services
    UserService::class,
    AuthService::class,
    Router::class,
]);
```

Error Handling
--------------

[](#error-handling)

The container provides clear, actionable error messages with helpful suggestions:

### Missing Type Hint

[](#missing-type-hint)

```
No type hint found for parameter '$logger'.
Type hints are required for dependency injection to work properly.

Add a type hint to the parameter, for example:
  public function __construct(YourClass $logger) { ... }

```

### Circular Dependency

[](#circular-dependency)

```
Circular dependency detected: ClassA -> ClassB -> ClassC -> ClassA

This happens when classes depend on each other in a loop.
Consider using setter injection or the factory pattern to break the cycle.

```

### Unresolvable Scalar

[](#unresolvable-scalar)

```
Unable to resolve parameter of type 'string' in 'UserService'.
Scalar types (string, int, float, bool, array) cannot be auto-resolved.

Provide a default value for the parameter:
  public function __construct(string $param = 'default') { ... }

```

### Service Not Found (with suggestions)

[](#service-not-found-with-suggestions)

```
No concrete class was found that implements:
"App\LogerInterface"
Did you forget to bind this interface to a concrete class?

Did you mean one of these?
  - App\LoggerInterface
  - App\Service\LoggerInterface

You might find some help here: https://gacela-project.com/docs/bootstrap/#bindings

```

Requirements
------------

[](#requirements)

- PHP &gt;= 8.1
- PSR-11 Container Interface

Testing
-------

[](#testing)

```
composer test          # Run tests
composer quality       # Run static analysis
composer test-coverage # Generate coverage report
```

Real-World Example
------------------

[](#real-world-example)

See how it's used in the [Gacela Framework](https://github.com/gacela-project/gacela/blob/main/src/Framework/ClassResolver/AbstractClassResolver.php#L142)

License
-------

[](#license)

MIT License. See [LICENSE](LICENSE) file for details.

###  Health Score

45

—

FairBetter than 93% of packages

Maintenance67

Regular maintenance activity

Popularity37

Limited adoption so far

Community17

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 84.6% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~104 days

Recently: every ~217 days

Total

10

Last Release

191d ago

PHP version history (2 changes)0.1.0PHP ^8.0, &lt;8.3

0.6.0PHP &gt;=8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/3d166420c6770c5941e10bd68b2d26501eabb432e280d8e6eba0a344bcc1e5ae?d=identicon)[Chemaclass](/maintainers/Chemaclass)

![](https://www.gravatar.com/avatar/104da2afcf190e1628dd0cbb29d4f404be41286642d23b51700002d60635ada1?d=identicon)[JesusValeraDev](/maintainers/JesusValeraDev)

---

Top Contributors

[![Chemaclass](https://avatars.githubusercontent.com/u/5256287?v=4)](https://github.com/Chemaclass "Chemaclass (104 commits)")[![JesusValeraDev](https://avatars.githubusercontent.com/u/6381924?v=4)](https://github.com/JesusValeraDev "JesusValeraDev (17 commits)")[![antonio-gg-dev](https://avatars.githubusercontent.com/u/13595197?v=4)](https://github.com/antonio-gg-dev "antonio-gg-dev (1 commits)")[![khru](https://avatars.githubusercontent.com/u/6353105?v=4)](https://github.com/khru "khru (1 commits)")

---

Tags

containerdependency-resolvergacelaphpresolverphpcontainerresolvergacela

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Psalm

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/gacela-project-container/health.svg)

```
[![Health](https://phpackages.com/badges/gacela-project-container/health.svg)](https://phpackages.com/packages/gacela-project-container)
```

###  Alternatives

[lctrs/psalm-psr-container-plugin

Let Psalm understand better psr11 containers

17648.1k13](/packages/lctrs-psalm-psr-container-plugin)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
