Bu örnekte form validation işleminin model class kullanarak nasıl yapıldığını göreceğiz. Model class uniqueConstraints ve UniqueEntity constraint hatalarını gösterme kabiliyetine sahip değildir, bu nedenle benzer hataları manuel olarak kendiniz aşağıdaki controllerde gösterildiği gibi yakalayabilirsiniz.


Entity


Varsayalım ki bu one-to-many ilişkinin many tarafı, Country ise ana tarafı.


namespace Football\FrontendBundle\Entity;

use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
* @ORM\Entity
* @ORM\Table(
* name="league",
* uniqueConstraints={@ORM\UniqueConstraint(columns={"name", "country_id"})}
* )
* @UniqueEntity(
* fields={"name","country"},
* message="League for given country already exists in database."
* )
*/
class League
{
/**
* @ORM\Id
* @ORM\Column(type="smallint")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;

/**
* @ORM\Column(name="name", type="string", length=100)
*/
protected $name;

/**
* @ORM\ManyToOne(
* targetEntity="Country",
* inversedBy="league"
* )
* @ORM\JoinColumn(
* name="country_id",
* referencedColumnName="id",
* onDelete="CASCADE",
* nullable=false
* )
*/
protected $country;
}

LeagueModel class


namespace Football\FrontendBundle\Model;

use Symfony\Component\Validator\Constraints as Assert;

class LeagueModel
{
/**
* @var string
*
* @Assert\NotBlank(message="Name is required.")
* @Assert\Length(
* max=100,
* maxMessage="Name cannot be longer than {{ limit }} characters."
* )
*/
protected $name;

/**
* @var string
*
* @Assert\NotBlank(message="Country is required.")
*/
protected $country;

public function getName()
{
return $this->name;
}

public function setName($name)
{
$this->name = $name;

return $this;
}

public function getCountry()
{
return $this->country;
}

public function setCountry($country)
{
$this->country = $country;

return $this;
}
}

FormType


namespace Football\FrontendBundle\Form\Type;

use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class LeagueType extends AbstractType
{
private $country;

public function __construct()
{
$this->country = [
'error_bubbling' => true,
'class' => 'FootballFrontendBundle:Country',
'property' => 'name',
'multiple' => false,
'expanded' => false,
'required' => false,
'empty_value' => '',
'query_builder' => function (EntityRepository $repo)
{
return $repo->createQueryBuilder('c')->orderBy('c.name', 'ASC');
}
];
}

public function buildForm(FormBuilderInterface $builder, array $options = [])
{
$builder
->setMethod($options['method'])
->setAction($options['action'])
->add('name', 'text', ['error_bubbling' => true])
->add('country', 'entity', $this->country);
}

public function getName()
{
return 'league';
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
['data_class' => 'Football\FrontendBundle\Model\LeagueModel']
);
}
}

Controller


/**
* @Route("/league")
*/
class LeagueController extends Controller
{
const ROUTER_PREFIX = 'football_frontend_league_';

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

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

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

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

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

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

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

$league = new League();
$league->setName($data->getName());
$league->setCountry($data->getCountry());

$em = $this->getDoctrine()->getManager();
$em->persist($league);
$em->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 LeagueException($message);
}

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

/**
* Creates form object.
*
* @param LeagueModel $league
* @param string $method
* @param string $action
*
* @return Form
*/
private function getForm(LeagueModel $league, $method, $action)
{
return $this->createForm(
new LeagueType(),
$league,
[
'method' => $method,
'action' => $action
]
);
}

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

Twig şablonu


{% extends 'FootballFrontendBundle:League:index.html.twig' %}

{% block body %}
{% spaceless %}
{{ parent() }}
LEAGUE - Create
<hr />
{{ form_start(form, {attr: {novalidate: 'novalidate'}}) }}
{% if form_errors(form) != '' %}

{{ form_errors(form) }}

{% endif %}

<p>NAME: {{ form_widget(form.name) }}</p>
<p>COUNTRY: {{ form_widget(form.country) }}</p>

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