Ich habe ein Formular, das zwei Entitäten (Benutzer und Profil) kombiniert.
Die Validierung scheint für den ersten Teil des Formulars zu funktionieren, der von der Benutzerentität stammt und die Grundlage des Formulars bildet.
Der ProfileType ist im UserType enthalten. Das Formular wird korrekt gerendert und zeigt die richtigen Informationen an, sodass es anscheinend ordnungsgemäß mit der Profilentität verbunden ist. Es ist nur die Validierung, die im ProfileType unterbrochen ist.
Irgendeine Idee, warum ein Teil validieren würde und der andere nicht?
Code unten:
Validation.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';
}
}
Regler
$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()));
Assert\Valid()
Annotation definiert ist, führt die erste Entität keine Kaskadenvalidierung für diese Eigenschaft durch. Alsocascade_validation
das Problem lösen.Ein Hinweis für Benutzer von Symfony 3.0 und höher: Die
cascade_validation
Option wurde entfernt . Verwenden Sie stattdessen Folgendes für eingebettete Formulare:$builder->add('embedded_data', CustomFormType::class, array( 'constraints' => array(new Valid()), ));
Es tut mir leid, dass ich diesen alten Thread mit einer leicht vom Thema abweichenden Antwort (Symfony 3 vs. 2) ergänzt habe, aber das Finden dieser Informationen hier hätte mir heute ein paar Stunden gespart.
quelle
use Symfony\Component\Validator\Constraints\Valid;
oben im Formular eine definitoin Datei hinzufügen . Symfony 4 hier.Gemäß der Dokumentation zum Formulartyp können Sie
Valid
anstelle dercascade_validation
Option auch eine Einschränkung verwenden .$builder->add('children', 'collection', array( 'type' => new ChildType(), 'constraints' => array(new Valid()), ));
Beispiel aus der Eigentümerentität:
/** * @var Collection * * @ORM\OneToMany(targetEntity="Child", ...) * @Assert\Valid() */ private $children
quelle
Ich habe genau das Gleiche gesucht und hier ist, was ich gefunden habe
http://symfony.com/doc/master/book/forms.html#forms-embedding-single-object
Sie müssen die Hauptentität anweisen, ihre Unterentitäten wie folgt zu validieren:
/** * @Assert\Type(type="AppBundle\Entity\Category") * @Assert\Valid() */ private $subentity;
Ich habe dies auf Symfony 2.8 getestet und es funktioniert.
quelle
Verwenden Sie YML oder Anmerkungen?
Ich habe versucht, die
cascade_validation
Option auf meine übergeordnete Formularklasse anzuwenden , aber die Validierung fand immer noch nicht statt. Nachdem ich eine kleine Dokumentation gelesen hatte, ging ich zuapp/config/config.yml
und stellte fest, dassenable_annotations
unterframework->validation
auf true gesetzt war . Wenn dies zutrifft, liest der Validierungsdienst anscheinend kein Einzelgänger validation.yml-Dateien. Also habe ich es einfach in false geändert und jetzt wird das Formular gut validiert.quelle
Gehört zu Symfony 2.3
Das Arbeiten mit eingebetteten Formularen und Validierungsgruppen kann sehr schmerzhaft sein: Annotation @Assert \ Valid () funktioniert bei mir nicht (ohne Gruppen ist es in Ordnung). Fügen Sie 'cascade_validation' => true in die DefaultOptions ein. Sie müssen dies nicht auf -> add () wiederholen. Achtung: Die HTML 5-Validierung funktioniert nicht mit Validierungsgruppen zusammen.
Beispiel:
Eine Sammlung von 2 Adressen. Beide 1: 1 unidirektional. Jeweils mit einer anderen (!) Validierungsgruppe.
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; //(...) }
Adressentität
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;
Adresstyp - Möglichkeit zum Ändern der Validierungsgruppe
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, )); } (...)
Und zuletzt den CollectionType
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 )); } //(...)
Ich hoffe es hilft..
quelle
Sie müssen hinzufügen
validation_groups
in IhrProfiletType
auch. Die Validierung erfolgt in jedem Formulartyp separat, basierend auf derendata_class
Vorhandensein.quelle
cascade_validation
Option in 2.1?Von meinem Controller:
$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();
Vierter Parameter in :: createNamedBuilder -
array('cascade_validation' => true))
quelle