I had a quick look at the different ways in which I could get my hands on the form builder in a Symfony 5 controller.
Disclaimer
1) other services are available and 2) this is not an exhaustive list on how to inject and/or access services in a controller.
So, as a starting point, let's assume we've installed Symfony 5.x (either with the Symfony CLI binary or with composer create project) and we have a lovely fresh installation. Let's open up a few files and see what we have... Here's what we'd expect to see in /config/services.yaml
// config/services.yaml
services:
_defaults:
autowire: true
// and a bit further down...
App\Controller\:
resource: '../src/Controller/'
tags: ['controller.service_arguments']
Now, if we uncomment the lines in /config/routes.yaml so we have...
// config/routes.yaml
index:
path: /
controller: App\Controller\DefaultController::index
and add a controller...
// src/Controller/DefaultController.php
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
class DefaultController extends AbstractController
{
public function index()
{
$formBuilder = $this->createFormBuilder();
return new Response('Yo!');
}
}
Bingo! We can start using the form builder.
Now if you're inheritance-adverse, you might not fancy extending the AbstractController class. Fear not! All we need to do is constructor-inject our dependency using type-hinting as follows:
// src/Controller/DefaultController.php
<?php
namespace App\Controller;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\Response;
class DefaultController
{
protected $formFactory;
public function __construct(FormFactoryInterface $formFactory)
{
$this->formFactory = $formFactory;
}
public function index()
{
$formBuilder = $this->formFactory->createBuilder();
return new Response('Yo!');
}
}
And this totally works because of the lovely auto-wiring provided by Symfony. Thanks, Symfony!
Lastly, let's take a look at how you'd get access to the form builder if you weren't, for whatever reason, using auto-wiring.
Let's disable auwiring in /config/services.yaml, tag our controller class with controller.service_arguments and bind the form factory service...
// config/services.yaml
services:
_defaults:
autowire: false
App\Controller\DefaultController:
tags: ['controller.service_arguments']
bind:
$formFactory: '@form.factory'
And finally, modify our controller...
// src/Controller/DefaultController.php
<?php
namespace App\Controller;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\Response;
class DefaultController
{
public function index(FormFactoryInterface $formFactory)
{
$formBuilder = $formFactory->createBuilder();
return new Response('Yo!');
}
}
And there we have it, I hope you enjoy playing around with these approaches.