Annotation-based autowiring for Symfony 4 dependency injection container
Add as Composer dependency:
$ composer require skrz/autowiring-bundle
Then add SkrzAutowiringBundle
to Symfony Kernel:
use Skrz\Bundle\AutowiringBundle\SkrzAutowiringBundle;
class AppKernel
{
public function registerBundles()
{
return [
...
new SkrzAutowiringBundle()
...
];
}
}
Annotate your application components using @Component
annotation and its subclasses, or so called "stereotypes".
Predefined stereotypes are @Controller
, @Repository
, and @Service
, e.g.:
use Skrz\Bundle\AutowiringBundle\Annotation\Controller;
/**
* @Controller
*/
class HomepageController
{
...
}
Create your own application stereotypes by subclassing @Component
.
// services.yml
services:
Example\HomepageController: ~
namespace Example;
use Skrz\Bundle\AutowiringBundle\Annotation\Controller;
/**
* @Controller
*/
class HomepageController
{
/**
* @var SomeService
*/
private $someService;
public function __construct(SomeService $someService)
{
$this->someService = $someService;
}
...
}
SomeService
is automatically injected into HomepageController
instance during creation in container.
Note that constructor is ALWAYS autowired if there is not enough arguments
specified in services.yml
. If you really
do not want the constructor to be autowired, add the service to ignored_services
configuration directive.
Note: if you need to specify some of the constructor arguments and autowire other constructor aurguments, you need to configure your service the following way:
// services.yml
services:
Example\HomepageController:
arguments:
someParameter: %kernel.whatever%
namespace Example;
use Skrz\Bundle\AutowiringBundle\Annotation\Controller;
/**
* @Controller
*/
class HomepageController
{
/**
* @var SomeService
*/
private $someService;
/**
* @var string
*/
private $someParameter;
public function __construct(SomeService $someService, $someParameter)
{
$this->someService = $someService;
$this->someParameter = $someParameter;
}
...
}
The $someService
argument is autowired and the $someParameter
argument is injected depending on the configuration.
// services.yml
services:
Example\HomepageController: ~
namespace Example;
use Skrz\Bundle\AutowiringBundle\Annotation\Controller;
use Skrz\Bundle\AutowiringBundle\Annotation\Autowired;
/**
* @Controller
*/
class HomepageController
{
/**
* @var SomeService
*/
private $someService;
/**
* @param SomeService $someService
* @return void
*
* @Autowired
*/
public function setSomeService(SomeService $someService)
{
$this->someService = $someService;
}
...
}
// services.yml
services:
Example\HomepageController: ~
namespace Example;
use Skrz\Bundle\AutowiringBundle\Annotation\Controller;
use Skrz\Bundle\AutowiringBundle\Annotation\Autowired;
/**
* @Controller
*/
class HomepageController
{
/**
* @var SomeService
*
* @Autowired
*/
public $someService;
...
}
Note: using property dependency injection is quite addictive.
You can also inject container parameters using @Value
annotation.
// services.yml
services:
Example\HomepageController: ~
namespace Example;
use Skrz\Bundle\AutowiringBundle\Annotation\Controller;
use Skrz\Bundle\AutowiringBundle\Annotation\Value;
/**
* @Controller
*/
class HomepageController
{
/**
* @var string
*
* @Value("%kernel.root_dir%")
*/
public $rootDir;
...
}
Pro-Tip: inject always scalar values, do not inject arrays. When you inject scalar values, their presence in container is validated during container compilation.
Autoscan was a feature of version 1.x of SkrzAutowiringBundle
. However, since Symfony 4.0, container supports
this feature
natively. Therefore, it was removed from the bundle and you should use resource
key to import directories of services.
// services.yml
services:
Example\:
resource: "../path/to/controllers/*Controller.php"
namespace Example;
use Skrz\Bundle\AutowiringBundle\Annotation\Controller;
use Skrz\Bundle\AutowiringBundle\Annotation\Autowired;
/**
* @Controller
*/
class HomepageController
{
/**
* @var SomeService
*
* @Autowired
*/
public $someService;
...
}
# container extension key is "autowiring"
autowiring:
# these service IDs won't be processed by autowiring
ignored_services:
# either specify exact service IDs
- kernel
- http_kernel
# or use regular expressions (they must start with "/")
- /^debug\./
- /^file/
# match interfaces to exact services
preferred_services:
Psr\Log\LoggerInterface: logger
Monolog\Logger: logger
Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface: session.storage.native
# if you create your own stereotypes, you must add then here
fast_annotation_checks: [ @Task, @Widget ]
The MIT license. See LICENSE file.