PHP code example of gacela-project / container

1. Go to this page and download the library: Download gacela-project/container library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

gacela-project / container example snippets


use Gacela\Container\Container;

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

$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

// 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);

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);

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)

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)

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);

$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

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

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

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

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

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

// 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'
]
*/

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

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

// 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

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

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

// Avoid setter injection (not supported)

// Good - type hint onstruct(LoggerInterface $logger) {}

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

// 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!

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

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