This may be a bit tricky so pay attention to every details. You need to inject some services to controller if you want to define controller as service so make sure you read Base Controller Methods and Their Service Replacements part.


Load YML config files


# sport/src/Football/FrontendBundle/DependencyInjection/FootballFrontendExtension.php
namespace Football\FrontendBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;

class FootballFrontendExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);

$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
$loader->load('repositories.yml');
$loader->load('controllers.yml');
}
}

Repositories YML


# sport/src/Football/FrontendBundle/Resources/config/repositories.yml
services:
football_frontend.repository.country:
class: Football\FrontendBundle\Repository\CountryRepository # Your repository class
factory_service: doctrine # Compulsory
factory_method: getRepository # Compulsory
arguments: [Football\FrontendBundle\Entity\Country] # Your actual entity class

Services YML


# sport/src/Football/FrontendBundle/Resources/config/services.yml
services:
football_frontend.service.form_error:
class: Football\FrontendBundle\Service\FormErrorService # An example class

Controllers YML


# sport/src/Football/FrontendBundle/Resources/config/controllers.yml
services:
football_frontend.controller.country:
class: Football\FrontendBundle\Controller\CountryController # Your controller
arguments:
- @router # Compulsory for urls
- @form.factory # Compulsory for forms
- @templating # Compulsory for twig tempaltes
- @doctrine.orm.entity_manager # Compulsory for EM
- @football_frontend.service.form_error # Your example service
- @football_frontend.repository.country # Your repository

Controller


# sport/src/Football/FrontendBundle/Controller/CountryController.php
namespace Football\FrontendBundle\Controller;

use Doctrine\DBAL\DBALException;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\ORMException;
use Exception;
use Football\FrontendBundle\Entity\Country;
use Football\FrontendBundle\Exception\CountryException;
use Football\FrontendBundle\Form\Type\CountryType;
use Football\FrontendBundle\Repository\CountryRepository;
use Football\FrontendBundle\Service\FormErrorServiceInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Component\Routing\RouterInterface;

/**
* @Route("/country", service="football_frontend.controller.country")
*/
class CountryController extends Controller
{
private $router;
private $formFactory;
private $templating;
private $entityManager;
private $formErrorService;
private $countryRepository;

public function __construct(
RouterInterface $router,
FormFactoryInterface $formFactory,
EngineInterface $templating,
EntityManager $entityManager,
FormErrorServiceInterface $formErrorService,
CountryRepository $countryRepository
) {
$this->router = $router;
$this->formFactory = $formFactory;
$this->templating = $templating;
$this->entityManager = $entityManager;
$this->formErrorService = $formErrorService;
$this->countryRepository = $countryRepository;
}

/**
* Landing page.
*
* @Route("")
* @Method({"GET"})
*
* @return Response
*/
public function listAction()
{
return $this->getFormView(
'list',
[
'countryArray' => $this->countryRepository->findAll()
]
);
}

/**
* Create page.
*
* @Route("/create")
* @Method({"GET"})
*
* @return Response
*/
public function createAction()
{
$form = $this->getForm(
new Country(),
'POST',
$this->router->generate(self::ROUTER_PREFIX . 'create')
);

return $this->getFormView('create', ['form' => $form->createView()]);
}

/**
* Creates processing.
*
* @param Request $request
*
* @Route("/create")
* @Method({"POST"})
*
* @return RedirectResponse|Response
* @throws CountryException
*/
public function createProcessAction(Request $request)
{
if ($request->getMethod() != 'POST') {
throw new CountryException('Country create: only POST method is allowed.');
}

$form = $this->getForm(
new Country(),
'POST',
$this->router->generate(self::ROUTER_PREFIX . 'create')
);
$form->handleRequest($request);

if (!$form->isSubmitted()) {
throw new CountryException('Country create: form is not submitted.');
}

if ($form->isValid() !== true) {
return $this->getFormView(
'create',
[
'form' => $form->createView(),
'errors' => $this->formErrorService->getErrors($form)
]
);
}

try {
$data = $form->getData();

$country = new Country();
$country->setCode($data->getCode());
$country->setName($data->getName());

$this->entityManager->persist($country);
$this->entityManager->flush();
} catch (DBALException $e) {
$message = sprintf('DBALException [%s]: %s', $e->getCode(), $e->getMessage());
} catch (ORMException $e) {
$message = sprintf('ORMException [%s]: %s', $e->getCode(), $e->getMessage());
} catch (Exception $e) {
$message = sprintf('Exception [%s]: %s', $e->getCode(), $e->getMessage());
}

if (isset($message)) {
throw new CountryException($message);
}

return $this->redirect($this->router->generate(self::ROUTER_PREFIX . 'list'));
}

/**
* Creates form object.
*
* @param Country $country
* @param string $method
* @param string $action
*
* @return Form
*/
private function getForm(Country $country, $method, $action)
{
return $this->formFactory->create(
new CountryType(),
$country,
[
'method' => $method,
'action' => $action
]
);
}

/**
* Creates webform.
*
* @param string $template
* @param array $parameters
*
* @return Response
*/
private function getFormView($template, array $parameters = [])
{
return $this->templating->renderResponse(
sprintf('FootballFrontendBundle:Country:%s.html.twig', $template),
$parameters
);
}
}

Twig template


# sport/src/Football/FrontendBundle/Resources/views/Country/create.html.twig
{% extends 'FootballFrontendBundle:Country:index.html.twig' %}

{% block body %}
{% spaceless %}
{{ parent() }}
COUNTRY - Create
<hr />
{{ form_start(form, { attr: {novalidate: 'novalidate'} }) }}
{% if errors is defined and errors is iterable %}
<div class="global-form-errors">
<ul>
{% for field, message in errors %}
<li>{{ message }}</li>
{% endfor %}
</ul>
</div>
{% endif %}

<p>CODE: {{ form_widget(form.code) }}</p>
<p>NAME: {{ form_widget(form.name) }}</p>

<p><button name="button">Submit</button></p>
{{ form_end(form) }}
{% endspaceless %}
{% endblock %}