devmachine/services-injector-bundle
Installation:
composer require devmachine/services-injector-bundle
Add to config/bundles.php:
return [
// ...
Devmachine\ServicesInjectorBundle\DevmachineServicesInjectorBundle::class => ['all' => true],
];
Enable Annotations:
Ensure SensioFrameworkExtraBundle is installed and configured (this bundle depends on it).
Add to config/packages/framework.yaml:
framework:
annotations:
resource: ['../src/']
autoload: true
First Use Case: Annotate a controller method to inject a service:
use Devmachine\ServicesInjectorBundle\Annotation\InjectService;
class MyController extends AbstractController
{
/**
* @InjectService("my_service_id")
*/
public function index(MyServiceInterface $service)
{
return $service->doSomething();
}
}
Service Injection in Controllers:
Use @InjectService on method arguments to auto-wire services:
/**
* @InjectService("mailer")
*/
public function sendWelcomeEmail(MailerInterface $mailer, string $email)
{
$mailer->send(...);
}
Combining with Type-Hinting: Leverage Symfony 3.3+ type-hinting for cleaner code:
public function index(UserRepositoryInterface $users) // Auto-injected if service exists
{
// ...
}
Conditional Injection:
Use @InjectService with optional parameters:
/**
* @InjectService("logger", optional=true)
*/
public function logAction(?LoggerInterface $logger = null)
{
if ($logger) {
$logger->info("Action triggered");
}
}
Grouped Services:
Inject multiple services at once via @InjectServices (if supported by the bundle):
/**
* @InjectServices({
* "service1": "service_id_1",
* "service2": "service_id_2"
* })
*/
public function complexAction(Service1Interface $service1, Service2Interface $service2)
{
// ...
}
Integration with DependencyInjection:
Define services in config/services.yaml:
services:
App\Service\MyService:
arguments:
$param: '%env(APP_PARAM)%'
Then inject via annotation:
/**
* @InjectService("App\Service\MyService")
*/
public function myAction(MyService $service)
{
// ...
}
Avoid Mixing Approaches: Stick to either annotations or type-hinting for consistency. Mixing may lead to conflicts.
Prioritize Type-Hinting:
Prefer Symfony’s native type-hinting (e.g., public function index(UserRepository $users)) over annotations where possible for maintainability.
Document Custom Services:
Annotate custom services in services.yaml with tags or aliases for clarity:
services:
App\Service\CustomLogger:
tags: ['app.logger']
alias: 'logger.custom'
Then inject via:
/**
* @InjectService("logger.custom")
*/
Testing: Mock services in tests by overriding the container:
$container->set('my_service', $mockService);
Performance:
Cache annotations if the bundle supports it (check config/packages/devmachine_services_injector.yaml for options).
Annotation Parsing Order:
services.yaml or loaded via bundles.Circular Dependencies:
ServiceA injects ServiceB, which injects ServiceA) will fail silently or throw cryptic errors.Autowire with lazy: true in services.yaml).Case Sensitivity:
"mailer" ≠ "Mailer".Override Conflicts:
services.yaml and via a bundle, the last definition wins. Annotations may not reflect the expected service.parent: in services.yaml.Deprecated Bundle:
nelmio/cors-bundle for modern alternatives.Annotation Caching:
php bin/console cache:clear) or use debug:config to verify mappings.Check Service Existence:
Run php bin/console debug:container to verify a service ID exists before annotating.
Enable Debug Mode:
Set APP_DEBUG=true in .env to see detailed annotation parsing errors.
Log Annotations:
Temporarily enable annotation logging in config/packages/devmachine_services_injector.yaml:
devmachine_services_injector:
debug: true
Inspect Compiled Code:
Check var/cache/dev/ for compiled annotation mappings (e.g., appDevDebugProjectContainer.php).
Fallback to Manual Injection: If annotations fail, manually inject services in the constructor:
public function __construct(private MyService $service) {}
Custom Annotations:
Extend the bundle by creating a custom annotation (e.g., @InjectScopedService) and hook into the bundle’s event system (if documented).
Service Aliases:
Define aliases in services.yaml to simplify injection:
services:
App\Service\MyService:
alias: 'app.my_service'
Then inject via @InjectService("app.my_service").
Dynamic Service Lookup: Use a closure in annotations (if supported) for dynamic service resolution:
/**
* @InjectService("service.{{ request.get('type') }}")
*/
public function dynamicAction($service)
{
// ...
}
Integration with Other Bundles:
Combine with stof/doctrine-extensions-bundle for ORM-specific services:
/**
* @InjectService("stof_doctrine_extensions.softdeleteable.manager")
*/
Environment-Specific Services:
Use %kernel.environment% in service IDs:
/**
* @InjectService("logger.{{ app.env('APP_ENV') }}")
*/
How can I help you explore Laravel packages today?