Eğer tek bir entity için yaratılan form validation işlemini iki ayrı forma yaymak isterseniz, aşağıda gösterildiği gibi symfony içindeki group validation özelliğini kullanabilirsiniz. Bu örnekte bir tane kullanıcı profili yaratmak için, iki ayrı form kullanacağız ve bu tek bir entity için geçerli olacak.


User entity


namespace Application\FrontendBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @ORM\Table(name="user")
*/
class User
{
/**
* @ORM\Id
* @ORM\Column(type="smallint")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;

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

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

/**
* @ORM\Column(name="middle_name", type="string", length=50, nullable=true)
*/
protected $middleName;

/**
* @ORM\Column(name="lucky_number", type="string", length=2, options={"fixed"=true})
*/
protected $luckyNumber;

/**
* @ORM\Column(name="favorite_colour", type="string", length=50, nullable=true)
*/
protected $favoriteColour;

/**
* @return integer
*/
public function getId()
{
return $this->id;
}

/**
* @param string $name
* @return User
*/
public function setName($name)
{
$this->name = $name;

return $this;
}

/**
* @return string
*/
public function getName()
{
return $this->name;
}

/**
* @param string $surname
* @return User
*/
public function setSurname($surname)
{
$this->surname = $surname;

return $this;
}

/**
* @return string
*/
public function getSurname()
{
return $this->surname;
}

/**
* @param string $middleName
* @return User
*/
public function setMiddleName($middleName)
{
$this->middleName = $middleName;

return $this;
}

/**
* @return string
*/
public function getMiddleName()
{
return $this->middleName;
}

/**
* @param string $luckyNumber
* @return User
*/
public function setLuckyNumber($luckyNumber)
{
$this->luckyNumber = $luckyNumber;

return $this;
}

/**
* @return string
*/
public function getLuckyNumber()
{
return $this->luckyNumber;
}

/**
* @param string $favoriteColour
* @return User
*/
public function setFavoriteColour($favoriteColour)
{
$this->favoriteColour = $favoriteColour;

return $this;
}

/**
* @return string
*/
public function getFavoriteColour()
{
return $this->favoriteColour;
}
}

ProfileStepOneType.php


namespace Application\FrontendBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\NotBlank;

class ProfileStepOneType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options = [])
{
$builder
->setMethod($options['method'])
->setAction($options['action'])
->add(
'name',
'text',
[
'error_bubbling' => true,
'constraints' => [
new NotBlank(
[
'message' => 'Name is required.',
'groups' => ['step_one']
]
)
]
]
)
->add('middleName', 'text', ['error_bubbling' => true])
->add(
'surname',
'text',
[
'error_bubbling' => true,
'constraints' => [
new NotBlank(
[
'message' => 'Surname is required.',
'groups' => ['step_one']
]
)
]
]
);
}

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

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(['data_class' => 'Application\FrontendBundle\Entity\User']);
}
}

ProfileStepTwoType.php


namespace Application\FrontendBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\NotBlank;

class ProfileStepTwoType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options = [])
{
$builder
->setMethod($options['method'])
->setAction($options['action'])
->add(
'luckyNumber',
'text',
[
'error_bubbling' => true,
'constraints' => [
new NotBlank(
[
'message' => 'Lucky Number is required.',
'groups' => ['step_two']
]
)
]
]
)
->add('favoriteColour', 'text', ['error_bubbling' => true]);
}

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

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(['data_class' => 'Application\FrontendBundle\Entity\User']);
}
}

Controllers.yml


services:
application_frontend.controller.profile:
class: Application\FrontendBundle\Controller\ProfileController
arguments:
- @router
- @form.factory
- @templating
- @doctrine.orm.entity_manager
- @session

ProfileController.php


namespace Application\FrontendBundle\Controller;

use Application\FrontendBundle\Entity\User;
use Application\FrontendBundle\Form\ProfileStepOneType;
use Application\FrontendBundle\Form\ProfileStepTwoType;
use Doctrine\DBAL\DBALException;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\ORMException;
use Exception;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\RouterInterface;
use WebDriver\Exception\InvalidRequest;

/**
* @Route("profile", service="application_frontend.controller.profile")
*/
class ProfileController extends Controller
{
const ROUTER_PREFIX = 'application_frontend_profile_';

private $router;
private $formFactory;
private $templating;
private $entityManager;
private $session;

public function __construct(
RouterInterface $router,
FormFactoryInterface $formFactory,
EngineInterface $templating,
EntityManager $entityManager,
SessionInterface $session
) {
$this->router = $router;
$this->formFactory = $formFactory;
$this->templating = $templating;
$this->entityManager = $entityManager;
$this->session = $session;
}

/**
* @Method({"GET"})
* @Route("/step_one")
*/
public function stepOneAction()
{
$form = $this->getForm(
new User(),
new ProfileStepOneType(),
'POST',
$this->router->generate(self::ROUTER_PREFIX . 'stepone'),
['step_one']
);

return $this->getTemplate(
'step_one',
[
'form' => $form->createView(),
'header' => 'STEP ONE'
]
);
}

/**
* @Method({"GET"})
* @Route("/step_two")
*/
public function stepTwoAction()
{
if (!$this->session->has('profile')) {
throw new InvalidRequest('STEP TWO: You must complete Step One first.');
} else {
$profile = $this->session->get('profile');
if (!isset($profile['step_one'])) {
throw new InvalidRequest('STEP TWO: You must complete Step One first.');
}
}

$form = $this->getForm(
new User(),
new ProfileStepTwoType(),
'POST',
$this->router->generate(self::ROUTER_PREFIX . 'steptwo'),
['step_two']
);

return $this->getTemplate(
'step_two',
[
'form' => $form->createView(),
'header' => 'STEP TWO'
]
);
}

/**
* @param Request $request
*
* @Method({"POST"})
* @Route("/step_one")
*
* @return Response
*/
public function stepOneProcessAction(Request $request)
{
if ($request->getMethod() != 'POST') {
throw new MethodNotAllowedException('Step One: Only POST method is allowed.');
}

$form = $this->getForm(
new User(),
new ProfileStepOneType(),
'POST',
$this->router->generate(self::ROUTER_PREFIX . 'stepone'),
['step_one']
);
$form->handleRequest($request);

if (!$form->isSubmitted()) {
throw new BadRequestHttpException('Step One: Form is not submitted.');
}

if ($form->isValid() !== true) {
return $this->getTemplate(
'step_one',
[
'form' => $form->createView(),
'header' => 'STEP ONE',
'errors' => $form->getErrors()
]
);
}

$data = $form->getData();

$this->session->set(
'profile',
[
'step_one' => [
'name' => $data->getName(),
'middle_name' => $data->getMiddleName(),
'surname' => $data->getSurname()
]
]
);

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

/**
* @param Request $request
*
* @Method({"POST"})
* @Route("/step_two")
*
* @return Response
* @throws Exception
*/
public function stepTwoProcessAction(Request $request)
{
if ($request->getMethod() != 'POST') {
throw new MethodNotAllowedException('Step Two: Only POST method is allowed.');
}

$form = $this->getForm(
new User(),
new ProfileStepTwoType(),
'POST',
$this->router->generate(self::ROUTER_PREFIX . 'steptwo'),
['step_two']
);
$form->handleRequest($request);

if (!$form->isSubmitted()) {
throw new BadRequestHttpException('Step Two: Form is not submitted.');
}

if ($form->isValid() !== true) {
return $this->getTemplate(
'step_two',
[
'form' => $form->createView(),
'header' => 'STEP TWO',
'errors' => $form->getErrors()
]
);
}

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

$luckyNumber = $data->getLuckyNumber();
$favoriteColour = $data->getFavoriteColour();
$profile = $this->session->get('profile');
$this->session->remove('profile');

$user = new User();
$user->setName($profile['step_one']['name']);
$user->setMiddleName($profile['step_one']['middle_name']);
$user->setSurname($profile['step_one']['surname']);
$user->setLuckyNumber($luckyNumber);
$user->setFavoriteColour($favoriteColour);

$this->entityManager->persist($user);
$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 Exception($message);
}

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

/**
* @param object $object
* @param object $form
* @param string $method
* @param string $action
* @param array $validationGroups
*
* @return Form
*/
private function getForm($object, $form, $method, $action, array $validationGroups = [])
{
return $this->formFactory->create(
$form,
$object,
[
'method' => $method,
'action' => $action,
'validation_groups' => $validationGroups
]
);
}

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

Step_one.html.twig


{% block body %}
{% spaceless %}
{{ parent() }}
{{ form_start(form, { attr: {novalidate: 'novalidate'} }) }}
{% if form_errors(form) != '' %}

{{ form_errors(form) }}
{% endif %}

<p>NAME: {{ form_widget(form.name) }}</p>
<p>MIDDLE NAME: {{ form_widget(form.middleName) }}</p>
<p>SURNAME: {{ form_widget(form.surname) }}</p>

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

Step_two.html.twig


{% block body %}
{% spaceless %}
{{ parent() }}
{{ form_start(form, { attr: {novalidate: 'novalidate'} }) }}
{% if form_errors(form) != '' %}

{{ form_errors(form) }}
{% endif %}

<p>LUCKY NUMBER: {{ form_widget(form.luckyNumber) }}</p>
<p>FAVORITE COLOUR: {{ form_widget(form.favoriteColour) }}</p>

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

Formlar