I have a form like this made with Symfony2:
class UsuarioRegistroType extends AbstractType {
public function BuildForm(FormBuilderInterface $builder, array $options) {
$builder->add('email', 'email', array('label' => 'E-mail', 'required' => true))
....
Forms works fine, but if I write something like Email: asdf (not email address), I never get the error assosiated with this issue. Also, if I don't write anything, I don't get any error for required constraint.
Any idea with this issue?
Thanks :)
Required true don't validate anything. It just add a class required on the field on the form view. It's the html5 which validate that.
Try to add that on UsuarioRegistroType class :
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$collectionConstraint = new Collection(array(
'email' => array(
new NotBlank(array('message' => 'Email should not be blank.')),
new Email(array('message' => 'Invalid email address.'))
)
));
$resolver->setDefaults(array(
'constraints' => $collectionConstraint
));
}
don't forget the use statements :
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Collection;
You have just used HTML5 validation, many barowser do not support this. With this old version of different famous browser also not support HTML5 validation.
I think you should use annotation for validation from serverside. I think you know about annotation , which you can use in your Entity class. In your enity class property you may defined your required validation rules using annotaion in symfony2.
Example:
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
/**
* #Assert\Email(
* message = "The email '{{ value }}' is not a valid email.",
* checkMX = true
* )
*/
protected $email;
}
Helpful link from Symfony2 official documentation: Symfony2 Validation
Related
I started to learn Sylius few days ago. I need an ecommerce module within my Symfony 3 project. So I gonna extend my project with Sylius, I'll just use the Core/Components stack.
I started with the installation of the Sylius ProductBundle (cf. http://docs.sylius.org/en/latest/bundles/SyliusProductBundle/installation.html)
Seems simple but didn't work at first because Composer installed a stable version (0.19) which is not supported anymore... Anyway, I finally installed the sylius/sylius ~1.0#dev package so my composer.json looks like that :
"minimum-stability" : "dev",
"prefer-stable" : true,
"require" : {
"php" : "^7.0",
"sylius/sylius" : "^1.0#beta",
"friendsofsymfony/user-bundle" : "~2.0#dev",
"symfony/assetic-bundle" : "^2.8",
"gedmo/doctrine-extensions" : "^2.4"
},
=> First question : is this the right way ???
Then I created a SyliusBundle within my project to decouple the entire Sylius configuration from the rest of my project.
In SyliusBundle/app/config.yml :
imports:
- { resource: "#SyliusProductBundle/Resources/config/app/config.yml" }
# Doctrine
stof_doctrine_extensions:
default_locale: "%locale%"
orm:
default:
tree: true
sluggable: true
timestampable: true
loggable: false
sortable: true
# Product
sylius_product:
driver: doctrine/orm
resources:
product:
classes:
model: OfferBundle\Entity\Offer
repository: OfferBundle\Entity\OfferRepository
form: OfferBundle\Form\OfferType
I followed the Sylius guideline to customize my Offer model inherited from Sylius Product model (quite simple)
in OfferBundle/Entity/Offer.php :
<?php
namespace OfferBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Sylius\Component\Core\Model\Product as BaseProduct;
/**
* #ORM\Table(name="offer")
* #ORM\Entity(repositoryClass="OfferRepository")
*/
class Offer extends BaseProduct
{
=> question 2 : sounds good to you ?
Then I customized the form extended my Offer form with the Sylius Product form (cf. http://docs.sylius.org/en/latest/customization/form.html)
in OfferBundle/Form/OfferType.php :
<?php
namespace OfferBundle\Form;
use Symfony\Component\OptionsResolver\OptionsResolver;
use OfferBundle\Entity\Offer;
use Symfony\Component\Form\AbstractType;
class OfferType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(['data_class' => Offer::class]);
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'offer';
}
/**
* {#inheritdoc}
*/
public function getParent()
{
return \Sylius\Bundle\ProductBundle\Form\Type\ProductType::class;
}
}
In OfferBundle/Form/Extension/OfferTypeExtension.php :
<?php
namespace OfferBundle\Form\Extension;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use AppBundle\Form\Type\WysiwygType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use OfferBundle\Form\Type\TagsType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use OfferBundle\Entity\Offer;
use MediaBundle\Form\MediaFileType;
use MediaBundle\Form\MediaVideoType;
use CompanyBundle\Entity\Company;
use Tetranz\Select2EntityBundle\Form\Type\Select2EntityType;
use Admin\CompanyBundle\Controller\CompanyController;
use Symfony\Component\Form\AbstractTypeExtension;
use OfferBundle\Form\ContactType;
use OfferBundle\Form\PriceType;
use OfferBundle\Form\OfferType;
final class OfferTypeExtension extends AbstractTypeExtension
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('advantage', WysiwygType::class)
->add('ecommerce')
->add('enabled')
->add('bestseller')
->add('company', Select2EntityType::class, [
'multiple' => false,
'remote_route' => 'admin_company_company_autocomplete',
'class' => Company::class,
'primary_key' => 'id',
'text_property' => 'name',
'minimum_input_length' => 0,
'page_limit' => CompanyController::NB_PER_PAGE,
'allow_clear' => false,
'delay' => 250,
'cache' => false,
'cache_timeout' => 60000,
'language' => 'fr',
'placeholder' => 'form.choose',
'required' => true,
])
->add('state', ChoiceType::class, [
'choices' => Offer::getStates(),
'placeholder' => 'form.choose',
])
...
And the form extension is loaded by service.
in OfferBundle/Resources/config/services.yml :
offer.form.extension.type.offer:
class: OfferBundle\Form\Extension\OfferTypeExtension
tags:
- { name: form.type_extension, extended_type: OfferBundle\Form\OfferType }
Question 3 : It works BUT in see that Sylius\Bundle\CoreBundle\Form\Extension\ProductTypeExtension contains additionnal fields like $images, $variantSelectionMethod... But it doesn't appear in my form. So I suppose that a service.yml somewhere is not loaded ?
Hope somebody can help me on that !
I think the problem is because you have overridden the form, and not extended it. So you only see your form fields, and not the Product form fields (as this form is not used anymore).
If you want to have the Product form with some changes, you only have to make a form extension to modify the existing Product form.
http://docs.sylius.org/en/latest/customization/form.html
Hope this helps ! :)
you may also need to override the template of the form in order to show those added fields.
Please respect me I am new in symfony, and I want to validate form if valid and or already exist. The user is able to submit form and save the data in database, the problem is the user is able to submit duplicate email at the same time. How do I do this.
namespace SwipeBundle\Controller\Backend;
use SwipeBundle\Entity\Company;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\EmailValidator;
public function addAction(Request $request)
{
$company = new Company;
$form = $this->createFormBuilder($company)
->add('name', TextType::class)
->add('prefund_wallet', TextType::class)
->add('telephone_no', TextType::class)
->add('mobile_no', TextType::class)
->add('address', TextareaType::class )
->add('email_address', EmailType::class)
->add('website', TextType::class)
->add('Submit', SubmitType::class)
->getForm();
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid())
{
$name = $form['name']->getData();
$prefund_wallet = $form['prefund_wallet']->getData();
$telephone_no = $form['telephone_no']->getData();
$mobile_no = $form['mobile_no']->getData();
$address = $form['address']->getData();
$email_address = $form['email_address']->getData();
$website = $form['website']->getData();
$ip = $request->getClientIp();
$now = new\DateTime('now');
// Check if email is valid
$emailValidator = new EmailValidator();
if(!$emailValidator->isValid($email_address, new Email()))
{
$form['email_address']->addError(new FormError('Invalid email'));
}
$company->setName($name);
$company->setPrefundWallet($prefund_wallet);
$company->setTelephoneNo($telephone_no);
$company->setMobileNo($mobile_no);
$company->setAddress($address);
$company->setEmailAddress($email_address);
$company->setRegistered($now);
$company->setIp($ip);
$company->setWebsite($website);
$em = $this->getDoctrine()
->getManager();
$em->persist($company);
$em->flush();
$this->addFlash(
'notice', 'Company has been added.'
);
die("Redirected");
}
return $this->render('Backend/Company/create.html.twig', array(
'form' => $form->createView()
));
}
Well, some didn't read the words "new to symfony"...
First thing to do is set your e-mail to unique in your entity:
/**
* #var string
*
* #ORM\Column(name="email_address", type="string", length=255, unique=true)
*/
private $emailAddress;
Don't forget to execute doctrine:schema:update --force
Next step would be what you already did, set the type in the FormType.
Btw, you don't need to add TextType::class everywhere...
->add('email_address', EmailType::class)
And to check if email isn't from some anonymous yopmail or stuff like that, you will need to create a service which will check the e-mail domain.
You can also do it in the FormType as well, but you will need to do it for every FormType, thus a service would be better. You can easily find here about how to create a service. If you really need help, comment, and I will write down an exemple.
You can find a list of those anonymous email services a bit everywhere, google is your friend.
you can check email validation directly on entity level.
Look at http://symfony.com/doc/current/reference/constraints/Email.html
And to check is unique use
https://symfony.com/doc/current/reference/constraints/UniqueEntity.html
If you do it right - it'll be only 2 lines (2 asserts) of code in Entity
I use FOSUserBundle with a custom registration form that extends the one provided by the bundle. I want to override the validation so it doesn't check for a username (I generate it). I have read that this can be achieved thru the usage of validation groups.
These are the relevant parts of my form:
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
...
$builder->remove('username');
...
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Ysu\Bundle\SiteBundle\Entity\User',
'validation_groups' => array('my-registration-group'),
'cascade_validation' => true
));
}
...
However the username is still validated with the validation files provided by the bundle. I found out that $options (array) contains an array validation_groupswhich in its turn contains the 'Registration' group, so that is why the field is still validated. However, I don't know how to remove it. If I unset it from $optionsbefore passing it to parent::buildFormit will still contain the Registration group.
Does anyone know how to solve this?
Turns out you can configure the validation groups for the FOSUserBundle's forms in config.yml:
fos_user:
....
registration:
form:
validation_groups: [default, registration_mod]
....
I have a problem. I need to validate a field that is not in entity in form type class. Previously I used this code:
$builder->addValidator(new CallbackValidator(function(FormInterface $form){
if (!$form['t_and_c']->getData()) {
$form->addError(new FormError('Please accept the terms and conditions in order to registe'));
}
}))
But since Symfony 2.1 method addValidator and class CallbackValidator are deprecated. Does anyone know what I should use instead?
I've done it in this way:
add('t_and_c', 'checkbox', array(
'property_path' => false,
'constraints' => new True(array('message' => 'Please accept the terms and conditions in order to register')),
'label' => 'I agree'))
The interface FormValidatorInterface was deprecated and will be removed in Symfony 2.3.
If you implemented custom validators using this interface, you can
substitute them by event listeners listening to the
FormEvents::POST_BIND (or any other of the *BIND events). In case
you used the CallbackValidator class, you should now pass the callback
directly to addEventListener.
via https://github.com/symfony/symfony/blob/master/UPGRADE-2.1.md#deprecations
For anyone else looking for help changing their validators to event subscribers (as it is slightly different to normal subscribers) follow this:
Step 1
Change:
$builder->addValidator(new AddNameFieldValidator());
to
$builder->addEventSubscriber(new AddNameFieldSubscriber());
Step 2
Replace your validator class (and all the namespaces) to a subscriber class.
Your subscriber class should look like the following:
// src/Acme/DemoBundle/Form/EventListener/AddNameFieldSubscriber.php
namespace Acme\DemoBundle\Form\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormError;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class AddNameFieldSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(FormEvents::POST_BIND => 'postBind');
}
public function postBind(FormEvent $event)
{
$data = $event->getData();
$form = $event->getForm();
$form->addError(new FormError('oh poop'))
}
}
You do not need to register the subscriber in a service file (yml or otherwise)
Reference:
http://symfony.com/doc/2.2/cookbook/form/dynamic_form_modification.html#adding-an-event-subscriber-to-a-form-class
I am attempting to override the RegistrationFormType in the Symfony2 FOSUserBundle. I am following the documentation and believe i've covered everything. I've created a bundle to contain my overrides to the FOSUserBundle and the following code is from this bundle as well as the application config.
Has anyone experienced this when overriding FOSUserBundle, or see anything in my code that would help explain why I keep getting this error.
I'm on symfony v2.0.4
RegistrationFormType.php
<?php
/*
* This file is part of the FOSUserBundle package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Thrive\SaasBundle\Form\Type;
use Symfony\Component\Form\FormBuilder;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;
class RegistrationFormType extends BaseType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('firstname', null, array('error_bubbling' => true))
->add('lastname', null, array('error_bubbling' => true))
->add('company', null, array('error_bubbling' => true))
->add('email', 'email', array('error_bubbling' => true))
->add('username', null, array('error_bubbling' => true))
->add('plainPassword', 'repeated', array('type' => 'password', 'error_bubbling' => true))
;
}
public function getName()
{
return 'thrive_user_registration';
}
}
Services.yml
services:
thrive_saas_registration.form.type:
class: Thrive\SaasBundle\Form\Type\RegistrationFormType
arguments: [%fos_user.model.user.class%]
tags:
- { name: form.type, alias: thrive_user_registration}
Application's Config File
fos_user:
...
registration:
form:
type: thrive_user_registration
Turns out my services.yml file wasn't being loaded via dependency injection. After digging around i realized my extension.php file for this bundle was named incorrectly. Early on I had renamed the bundle and made a typo when renaming the extension.php file inside the DependencyInjection folder. After correcting the mispelling everything works again.
Did you tried to just add one new field and look if it works?
public function buildForm(FormBuilder $builder, array $options)
{
parent::buildForm($builder, $options);
// add your custom field
$builder->add('name');
}
Also remember to clear your prod cache if you're testing from there...