PHP code example of quellabs / dependency-injection

1. Go to this page and download the library: Download quellabs/dependency-injection 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/ */

    

quellabs / dependency-injection example snippets


// Create a container
$container = new \Quellabs\DependencyInjection\Container();

// Checks if the container can resolve the class or interface
$canResolve = $container->has(MyService::class);

// Get a service (automatically resolves all dependencies)
$service = $container->get(MyService::class);

// Create a new instance without service providers
$instance = $container->make(MyService::class);

// Call a method with autowired dependencies
$result = $container->invoke($service, 'doSomething', ['extraParam' => 'value']);

// Check before resolving
if ($container->has(LoggerInterface::class)) {
    $logger = $container->get(LoggerInterface::class);
}

// Uses service providers (singleton by default)
$service = $container->get(MyService::class);
$sameService = $container->get(MyService::class); // Returns the same instance

// Works with contextual resolution
$objectQuelEM = $container->for('objectquel')->get(EntityManagerInterface::class);

// Always creates a new instance, bypassing service providers
$instance1 = $container->make(MyService::class);
$instance2 = $container->make(MyService::class); // Creates a different instance

// Still supports parameter injection
$instance = $container->make(MyService::class, ['customParam' => 'value']);

// Service provider pattern - recommended for services
$logger = $container->get(LoggerInterface::class);        // Uses LoggerServiceProvider
$cache = $container->get(CacheInterface::class);          // Uses CacheServiceProvider

// Direct instantiation - good for temporary objects
$request = $container->make(HttpRequest::class);          // New instance every time
$validator = $container->make(FormValidator::class);      // Fresh validator

// Mixed usage example
class OrderService {
    public function __construct(
        private LoggerInterface $logger,     // Injected via get() (singleton)
        private EmailService $emailService  // Injected via get() (singleton)
    ) {}
    
    public function processOrder(array $orderData): void {
        // Create a fresh order processor for each order
        $processor = $this->container->make(OrderProcessor::class, [
            'orderData' => $orderData,
            'timestamp' => time()
        ]);
        
        $processor->process();
    }
}

// Get a specific implementation using context
$objectQuelEM = $container->for('objectquel')->get(EntityManagerInterface::class);
$doctrineEM = $container->for('doctrine')->get(EntityManagerInterface::class);

// Create a contextual container with 'objectquel' context
$objectQuelContainer = $container->for('objectquel');

// Now get multiple services, all using the 'objectquel' context
$em = $objectQuelContainer->get(EntityManagerInterface::class);           // ObjectQuel EntityManager
$queryBuilder = $objectQuelContainer->get(QueryBuilderInterface::class);  // ObjectQuel QueryBuilder

// Use complex context with multiple parameters
$cache = $container->for(['driver' => 'redis', 'cluster' => 'main'])->get(CacheInterface::class);

// Default behavior (no context)
$logger = $container->get(LoggerInterface::class); // Uses default provider

/**
 * Service Provider class for dependency injection
 * Extends the base ServiceProvider from Quellabs eco system
 */
use Quellabs\DependencyInjection\Provider\ServiceProvider;

/**
 * Custom service provider that handles instantiation of specific services
 */
class MyServiceProvider extends ServiceProvider {

    /**
     * Determines if this provider can create the requested class
     * @param string $className The fully qualified class name to check
     * @param array $context Context information for provider selection (optional)
     * @return bool True if this provider supports creating the class
     */
    public function supports(string $className, array $context = []): bool {
        // Support either the exact MyService class or any class implementing MyInterface
        $supportsClass = $className === MyService::class || is_subclass_of($className, MyInterface::class);
        
        // Check context if provider name is specified
        if (isset($context['context'])) {
            return $supportsClass && $context['context'] === 'myservice';
        }
        
        return $supportsClass;
    }
    
    /**
     * Creates an instance of the requested class with dependencies injected
     * @param string $className The fully qualified class name to instantiate
     * @param array $dependencies Array of dependencies to inject into the constructor
     * @return object The instantiated object
     */
    public function createInstance(string $className, array $dependencies, array $metadata, ?MethodContext $methodContext=null): object
        // Instantiate the class by passing all dependencies to the constructor
        $instance = new $className(...$dependencies);
        
        // Apply post-instantiation configuration for specific service types
        if ($instance instanceof MyService) {
            // Call an initialization method if the instance is MyService
            $instance->initialize();
        }
        
        // Return the fully configured instance
        return $instance;
    }
}

$container->register(new MyServiceProvider());

// ObjectQuel Entity Manager Provider
class ObjectQuelServiceProvider extends ServiceProvider {
    public function supports(string $className, array $context = []): bool {
        return $className === EntityManagerInterface::class 
            && ($context['context'] ?? null) === 'objectquel';
    }
    
    public function createInstance(string $className, array $dependencies, array $metadata, ?MethodContext $methodContext=null): object
        return new ObjectQuelEntityManager($this->createConfiguration());
    }
}

// Doctrine Entity Manager Provider  
class DoctrineServiceProvider extends ServiceProvider {
    public function supports(string $className, array $context = []): bool {
        return $className === EntityManagerInterface::class 
            && ($context['context'] ?? null) === 'doctrine';
    }
    
    public function createInstance(string $className, array $dependencies, array $metadata, ?MethodContext $methodContext=null): object
        return new DoctrineEntityManager($this->createConfiguration());
    }
}

// Usage
$objectQuelEM = $container->for('objectquel')->get(EntityManagerInterface::class);
$doctrineEM = $container->for('doctrine')->get(EntityManagerInterface::class);

use Quellabs\DependencyInjection\Provider\SimpleBinding;

// Instead of creating a full ServiceProvider class
$container->register(new SimpleBinding(LoggerInterface::class, FileLogger::class));

class LoggerProvider extends ServiceProvider {
    public function supports(string $className, array $context): bool {
        return $className === LoggerInterface::class;
    }
    
    public function createInstance(...): object {
        return new FileLogger(...$dependencies);
    }
}
$container->register(new LoggerProvider());

use Quellabs\DependencyInjection\Provider\ServiceProvider;

/**
 * TransientServiceProvider specializes in providing non-singleton instances.
 * When a class is supported by this provider, a new instance will be created
 * for each request/resolution rather than being cached and reused.
 */
class TransientServiceProvider extends ServiceProvider {
    
    /**
     * Determines if this provider should handle the requested class.
     * @param string $className The fully qualified class name to check
     * @param array $context Context information for provider selection (optional)
     * @return bool True if this provider should create the instance
     */
    public function supports(string $className, array $context = []): bool {
        // Define which classes should be created as new instances each time
        // These are typically stateful classes that shouldn't be shared between requests
        return in_array($className, [
            RequestContext::class,    // Contains request-specific data
            TemporaryData::class      // Holds temporary state that shouldn't persist
        ]);
    }
    
    /**
     * Creates a new instance of the requested class.
     * @param string $className The class to instantiate
     * @param array $dependencies Array of constructor dependencies already resolved
     * @return object A new instance of the requested class
     */
    public function createInstance(string $className, array $dependencies, array $metadata, ?MethodContext $methodContext=null): object
        // Always create a new instance without caching
        // The spread operator (...) unpacks the dependencies array as arguments
        return new $className(...$dependencies);
    }
}

// These will be different instances
$processor1 = $container->make(OrderProcessor::class);
$processor2 = $container->make(OrderProcessor::class);

// Versus singleton behavior with get()
$service1 = $container->get(OrderService::class);
$service2 = $container->get(OrderService::class); // Same instance as service1

class ConfigurableService {
    public function __construct(
        private DatabaseConnection $db,
        private LoggerInterface $logger,
        private array $__all__ = []
    ) {
        // $db and $logger are resolved normally
        // $__all__ contains all parameters passed to the container
    }
}

// Usage
$service = $container->get(ConfigurableService::class, [
    'database_host' => 'localhost',
    'log_level' => 'debug',
    'api_key' => 'secret123'
]);

// Inside ConfigurableService constructor:
// $__all__ = [
//     'database_host' => 'localhost',
//     'log_level' => 'debug', 
//     'api_key' => 'secret123'
// ]

$container = new \Quellabs\DependencyInjection\Container(null, true);

$container = new \Quellabs\DependencyInjection\Container('/path/to/app');

$container = new \Quellabs\DependencyInjection\Container(null, false, 'custom-key');