Symfony2 - Walidacja nie działa dla wbudowanego typu formularza
Mam formularz, który łączy dwa byty (użytkownik I Profil).
Walidacja wydaje się działać na pierwszej części formularza, która pochodzi z jednostki użytkownika i jest podstawą formularza.
ProfileType jest zawarty wewnątrz typu UserType. Formularz renderuje się poprawnie i wyświetla prawidłowe informacje, więc wydaje się, że jest prawidłowo połączony z podmiotem profilu. To tylko Walidacja, która jest zepsuta na profilu.
Każdy pomysł, dlaczego jedna część miałaby walidować a drugi nie?
Kod poniżej:
Walidacja.yml
DEMO\DemoBundle\Entity\User\Profile:
properties:
address1:
- NotBlank: { groups: [profile] }
name:
- NotBlank: { groups: [profile] }
companyName:
- NotBlank: { groups: [profile] }
DEMO\DemoBundle\Entity\User\User:
properties:
username:
- NotBlank:
groups: profile
message: Username cannot be left blank.
email:
- NotBlank:
groups: profile
message: Email cannot be left blank
- Email:
groups: profile
message: The email "{{ value }}" is not a valid email.
checkMX: true
password:
- MaxLength: { limit: 20, message: "Your password must not exceed {{ limit }} characters." }
- MinLength: { limit: 4, message: "Your password must have at least {{ limit }} characters." }
- NotBlank: ~
UserType.php
namespace DEMO\DemoBundle\Form\Type\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\CallbackValidator;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormError;
use DEMO\DemoBundle\Form\Type\User\ProfileType;
class UserType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('username');
$builder->add('email');
$builder->add('profile', new ProfileType());
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'DEMO\DemoBundle\Entity\User\User',
'validation_groups' => array('profile')
);
}
public function getName()
{
return 'user';
}
}
ProfileType.php
namespace DEMO\DemoBundle\Form\Type\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\CallbackValidator;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormError;
class ProfileType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('name');
$builder->add('companyName', null, array('label' => 'Company Name'));
$builder->add('address1', null, array('label' => 'Address 1'));
$builder->add('address2', null, array('label' => 'Address 2'));
$builder->add('city');
$builder->add('county');
$builder->add('postcode');
$builder->add('telephone');
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'DEMO\DemoBundle\Entity\User\Profile',
);
}
public function getName()
{
return 'profile';
}
}
Controller
$user = $this->get('security.context')->getToken()->getUser();
$form = $this->createForm(new UserType(), $user);
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
// Get $_POST data and submit to DB
$em = $this->getDoctrine()->getEntityManager();
$em->persist($user);
$em->flush();
// Set "success" flash notification
$this->get('session')->setFlash('success', 'Profile saved.');
}
}
return $this->render('DEMODemoBundle:User\Dashboard:profile.html.twig', array('form' => $form->createView()));
8 answers
Spędziłem pewien czas szukając i stwierdziłem, że dodawanie {[2] } do tablicy setDefaults()
w klasie mojego rodzica, które ją naprawiło (jak wspomniano już w wątku). Powoduje to uruchomienie walidacji ograniczeń encji w typach potomnych pokazanych w formularzu. np.
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
...
'cascade_validation' => true,
));
}
W przypadku kolekcji należy również dodać 'cascade_validation' => true
do tablicy $options
dla pola collection w formularzu. np.
$builder->add('children', 'collection', array(
'type' => new ChildType(),
'cascade_validation' => true,
));
Spowoduje to, że Walidacja unikalności będzie miała miejsce tak, jak powinna w używanym podmiocie potomnym w kolekcji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-21 14:37:45
Uwaga dla użytkowników Symfony 3.0 i do góry: opcja cascade_validation
została usunięta . Zamiast tego użyj następujących form wbudowanych:
$builder->add('embedded_data', CustomFormType::class, array(
'constraints' => array(new Valid()),
));
Przepraszam, że dodałem do tego starego wątku nieco poza tematem (Symfony 3 vs. 2), ale znalezienie tej informacji tutaj zaoszczędziłoby mi dziś kilka godzin.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-14 13:17:51
Zgodnie z dokumentacją typu formularza można również użyć opcji Valid
constraint zamiast opcji cascade_validation
.
$builder->add('children', 'collection', array(
'type' => new ChildType(),
'constraints' => array(new Valid()),
));
Przykład z encji właściciela:
/**
* @var Collection
*
* @ORM\OneToMany(targetEntity="Child", ...)
* @Assert\Valid()
*/
private $children
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-29 14:55:59
Należy do Symfony 2.3
Praca z wbudowanymi formularzami i grupami walidacyjnymi może być dość bolesna: Adnotacja @ Assert\Valid() nie działa dla mnie (bez grup jest ok). Insert 'cascade_validation' = > true Na DefaultOptions jest kluczem. Nie musisz tego powtarzać na- > add (). Uważaj: Walidacja HTML 5 nie współpracuje z grupami walidacji.
Przykład:
Zbiór 2 adresów. Obie jednokierunkowe 1:1. Każdy z innym (!) Grupa walidacyjna.
class TestCollection{
//(...)
/**
* @var string
* @Assert\NotBlank(groups={"parentValGroup"})
* @ORM\Column(name="name", type="string", length=255, nullable=true)
*/
protected $name;
/**
* @var \Demo\Bundle\Entity\TestAddress
* @Assert\Type(type="Demo\Bundle\Entity\TestAddress")
* @ORM\OneToOne(targetEntity="TestAddress",cascade={"persist","remove"},orphanRemoval=true)
* @ORM\JoinColumn(name="billing_address__id", referencedColumnName="id")
*/
protected $billingAddress;
/**
* @var \Demo\Bundle\Entity\TestAddress
* @Assert\Type(type="Demo\Bundle\Entity\TestAddress")
* @ORM\OneToOne(targetEntity="TestAddress",cascade={"persist","remove"}, orphanRemoval=true)
* @ORM\JoinColumn(name="shipping_address__id", referencedColumnName="id")
*/
protected $shippingAddress;
//(...)
}
Podmiot Adresowy
class TestAddress {
/**
* @var string
* @Assert\NotBlank(groups={"firstname"})
* @ORM\Column(name="firstname", type="string", length=255, nullable=true)
*/
private $firstname;
/**
* @var string
* @Assert\NotBlank(groups={"lastname"})
* @ORM\Column(name="lastname", type="string", length=255, nullable=true)
*/
private $lastname;
/**
* @var string
* @Assert\Email(groups={"firstname","lastname"})
* @ORM\Column(name="email", type="string", length=255, nullable=true)
*/
private $email;
Typ adresu-możliwość zmiany grupy walidacji
class TestAddressType extends AbstractType {
protected $validation_group=['lastname'];//switch group
public function __construct($validation_group=null) {
if($validation_group!=null) $this->validation_group=$validation_group;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
//disable html5 validation: it suchs with groups
$builder
->add('firstname',null,array('required'=>false))
->add('lastname',null,array('required'=>false))
->add('email',null,array('required'=>false))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Demo\Bundle\Entity\TestAddress',
'validation_groups' => $this->validation_group,
));
}
(...)
I ostatni typ kolekcji
class TestCollectionType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{ $builder
->add('name')
->add('billingAddress', new TestAddressType(['lastname','firstname']))
->add('shippingAddress', new TestAddressType(['firstname']))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Demo\Bundle\Entity\TestCollection',
'validation_groups' => array('parentValGroup'),
'cascade_validation' => true
));
}
//(...)
Mam nadzieję, że to pomoże..Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-21 12:49:33
Musisz również dodać validation_groups
do swojego ProfiletType
. Walidacja odbywa się w każdym typie formularza oddzielnie na podstawie ich data_class
, jeśli istnieje.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-13 10:47:33
Używasz YML czy adnotacji?
Próbowałem zastosować opcję cascade_validation
Na mojej klasie formularza nadrzędnego, ale Walidacja nadal nie miała miejsca. Po przeczytaniu trochę dokumentacji, poszedłem do app/config/config.yml
i okazało się, że enable_annotations
Pod framework->validation
został ustawiony natrue . Najwyraźniej, jeśli to prawda, usługa walidacji no loner odczytuje walidację.pliki yml. Więc zmieniłem go na false , a teraz formularz jest poprawny.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-09 18:34:54
Szukałem dokładnie tego samego i oto co znalazłem
Http://symfony.com/doc/master/book/forms.html#forms-embedding-single-object
Musisz powiedzieć głównej jednostce, aby zweryfikowała jej sub-jednostki w ten sposób:
/**
* @Assert\Type(type="AppBundle\Entity\Category")
* @Assert\Valid()
*/
private $subentity;
Testowałem to na symfony 2.8 i działa.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-16 14:13:37
Z mojego kontrolera:
$form = $this->get('form.factory')
->createNamedBuilder('form_data', 'form', $item, array('cascade_validation' => true))
->add('data', new ItemDataType())
->add('assets', new ItemAssetsType($this->locale))
->add('contact', new ItemContactType())
->add('save', 'submit',
array(
'label' => 'Save',
'attr' => array('class' => 'btn')
)
)
->getForm();
Czwarty parametr w:: createNamedBuilder - array('cascade_validation' => true))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-11 22:03:10