Flex : mixing autowiring and old-fashioned service way
Context
Symfony Flex incredibly reduces and simplifies day-to-day Symfony usage. Among other things, autowiring is one of the biggest. But what if you need to use some old-school service naming for further usage ?
Solution
For the CMS bundle I'm working on, I needed to refer to an handler for security (successful/failure authentication). Docs states I can use a service name in security.yaml
:
admin:
provider: db_provider # Use any declared provider above
form_login:
login_path: /admin/login
check_path: /admin/login
default_target_path: /admin
username_parameter: login[username_or_email]
password_parameter: login[password]
success_handler: app.security_handler
failure_handler: app.security_handler
The handler :
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
class SecurityHandler implements AuthenticationSuccessHandlerInterface, AuthenticationFailureHandlerInterface
{
private $router;
public function __construct(RouterInterface $router)
{
$this->router = $router;
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
// TODO make necessary check to ensure proper redirection after successful authentication
return new RedirectResponse($this->router->generate('index'));
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
// TODO make necessary check to ensure proper redirection after failure authen authentication
return new RedirectResponse($this->router->generate('app_login'));
}
}
But from a Flex point of view, the constructor with type-hinted arguments is enough.
The solution is in 2 steps
- Define the service "old-fashioned" way
app.security_handler:
class: App\Listener\Security\SecurityHandler
But doing so, to core will switch to old way to load service. Meaning that you would have to provide parameters/services for dependancy injection manually.
- Define a service alias
App\Listener\Security\SecurityHandler: '@app.security_handler'
This very last step enable autowiring for your service. I can use the name in security.yaml as above.