Installation Run:
composer require 4xxi/strategy-injector
Ensure config/packages/strategy_injector.yaml exists with the basic structure.
First Use Case: Constructor Injection
Define a composite class (e.g., CompositeFooStrategy) that implements App\Strategy\FooStrategyInterface.
Configure the bundle to inject all implementing classes into the composite:
strategy_injector:
App\Strategy\FooStrategyInterface: App\Strategy\CompositeFooStrategy
First Use Case: Method Injection
Configure a method (e.g., addStrategy) to dynamically inject strategies:
strategy_injector:
App\Strategy\FooStrategyInterface:
method: 'addStrategy'
class: App\Strategy\CompositeFooStrategy
Verify Autowiring
Ensure your services.yaml includes:
App\Strategy\CompositeFooStrategy: ~
And that the composite class is properly tagged or autowired.
Define Interfaces and Implementations
Create a strategy interface (e.g., FooStrategyInterface) and multiple implementations (e.g., BarStrategy, BazStrategy).
Implement a composite class (e.g., CompositeFooStrategy) that aggregates these strategies.
Configure Constructor Injection Use the bundle to inject all implementations of an interface into the composite via its constructor:
strategy_injector:
App\Strategy\FooStrategyInterface: App\Strategy\CompositeFooStrategy
The composite’s constructor should accept an array of strategies:
public function __construct(array $strategies) { ... }
Dynamic Method Injection For runtime flexibility, configure method injection:
strategy_injector:
App\Strategy\FooStrategyInterface:
method: 'addStrategy' // Method on CompositeFooStrategy
class: App\Strategy\CompositeFooStrategy
The composite class must implement addStrategy to accept new strategies:
public function addStrategy(FooStrategyInterface $strategy) { ... }
Integration with Symfony Services Use the composite class in controllers/services:
use App\Strategy\CompositeFooStrategy;
class MyService {
public function __construct(private CompositeFooStrategy $composite) { ... }
}
Conditional Injection Extend the composite class to filter strategies based on runtime conditions (e.g., environment variables, user roles). Example:
public function __construct(array $strategies, $environment) {
$this->strategies = array_filter($strategies, fn($s) => $s->supports($environment));
}
Strategy Prioritization
Implement a getPriority() method in strategies and sort them in the composite:
public function __construct(array $strategies) {
usort($strategies, fn($a, $b) => $b->getPriority() <=> $a->getPriority());
$this->strategies = $strategies;
}
Lazy Loading Use method injection to add strategies on-demand (e.g., via API calls):
$composite->addStrategy(new DynamicStrategy());
Circular Dependencies
Ensure the composite class and its strategies do not create circular references in the container.
Fix: Use autowire: false and manually define services in services.yaml.
Missing Interface Implementations
If no classes implement App\Strategy\FooStrategyInterface, the composite will receive an empty array.
Fix: Validate configurations or provide default strategies.
Method Injection Mismatches
The configured method must exist in the composite class and accept the correct argument type.
Fix: Verify method signatures and use PHPDoc types for clarity.
Configuration Overrides
Bundle configurations in strategy_injector.yaml are merged; later entries override earlier ones.
Fix: Order configurations carefully or use unique keys.
Archived Package Risks
The package is archived; ensure no critical bugs exist or fork it if needed.
Fix: Test thoroughly and consider alternatives like league/tactician for production.
Log Injected Strategies Add debug output in the composite’s constructor/method to verify injected strategies:
public function __construct(array $strategies) {
\Log::debug('Injected strategies:', $strategies);
}
Validate YAML Syntax
Use Symfony’s config validator or symfony/var-dumper to inspect parsed configurations:
use Symfony\Component\DependencyInjection\ContainerInterface;
$config = $container->getParameter('strategy_injector');
Check Autowiring
Ensure the composite class is properly tagged or autowired in services.yaml:
App\Strategy\CompositeFooStrategy:
tags: ['strategy.injector.composite']
Custom Strategy Resolvers
Override the bundle’s resolver logic by extending StrategyInjector\Resolver\StrategyResolverInterface and binding it in the container.
Dynamic Strategy Discovery Implement a custom compiler pass to discover strategies at runtime (e.g., from a database):
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
Strategy Metadata
Add metadata (e.g., priority, enabled) to strategies via attributes or annotations and filter them in the composite:
#[Strategy(priority: 100)]
class HighPriorityStrategy implements FooStrategyInterface { ... }
Integration with Other Bundles
Combine with symfony/options-resolver for dynamic strategy configuration:
use Symfony\Component\OptionsResolver\OptionsResolver;
$resolver = new OptionsResolver();
$resolver->setDefaults(['strategies' => []]);
How can I help you explore Laravel packages today?