Optional embed form in Symfony 2

让人想犯罪 __ 提交于 2019-12-01 12:21:20

I would try this method:

create additional method in your Phone entity which validates if all fields are null or all fields are not null (these two cases are correct) - and then return true. If some fields are null and some aren't return false. Add an assert annotation to your new method - this will be your new constraint.

/**
 * @Assert\True(message = "Fill all fields or leave all them blank")
 */

And this should work.

For more information look here: http://symfony.com/doc/master/book/validation.html#getters

edit:

Try this one:

define your custom validation method (this one which check if any of phone fields is filled) as Callback (at the top of the class):

 * @Assert\Callback(methods={"checkPhoneFields"})
 */
 class Phone {

Next you mark field wich have to be validated with validation group, eg.

/**
 * @ORM\Column(type="string", length=16, groups={"phone_validation"})
 */
private $number;

And the last thing, in your custom constraint method you need to switch on "phone_validation" group if any of field isn't empty:

public function checkPhoneFields(ExecutionContext $context) {
    if (/* fields are not empty */) {
        $context->getGraphWalker()->walkReference($this, 'phone_validation', $context->getPropertyPath(), true);
    }

And that should work.

For those passing by, with newer versions of Symfony you can do :

/**
 *
 * @Assert\Callback()
 */
public function validatePhone(ExecutionContextInterface $context)
{
    if (/* Fields are not empty */)
    {
        $context->validate($this->getPhone(), 'phone', array("phone_validation"));
    }
}

Do this:

First on your phone entity, declare the fields as "nullable" like this:

/**
 * @ORM\Column(type="integer", nullable=true)
 */
private $countryCode;

This will allow these fields to have a null value.

Then you need to declare a validator that will check if either none of the fields or all of them are filled

class Phone {

...
/**
 * @Assert\True(message = "Phone must be empty of fill all fields")
 */
public function isPhoneOK()
{
    // check if no field is null or all of them are
    // return false if these conditions are not met
}

It is also possible to use a very simple data Transformer to solve this problem.

  1. Create your Phone data transformer :

    class PhoneTransformer implements DataTransformerInterface
    {
        public function transform($phone)
        {
            if (is_null($phone))
                return new Phone();
    
            return $phone;
        }
    
        public function reverseTransform($phone)
        {
            if (is_null($phone))
                return null;
    
            if (!$phone->getType() && !$phone->getCountryCode() /* ... Test if phone is not valid here */)
                return null;
    
            return $phone;
    }
    
  2. Then simply prepend this transformer in your PhoneType form :

    class PhoneType extends AbstractType
    {
        public function buildForm(FormBuilder $builder, array $options)
        {
            $builder
                /* Add fields here :
                ->add( ... )
                */
                ->prependNormTransformer(new PhoneTransformer())
            ;
        }
    }
    

See http://symfony.com/doc/2.0/cookbook/form/data_transformers.html for more details on how implement data transformers.

Esteban Filardi

frankie567's answer was useful to me. For symfony >= 3.0:

/**
 *
 * @Assert\Callback()
 */
public function validatePhone(ExecutionContextInterface $context)
{
    if (/* Fields are not empty */)
    {
        $validator = $context->getValidator();

        $validator->inContext($context)
            ->atPath('phone')
            // you can pass custom validation instead of null, like new Assert\Valid()
            ->validate($this->getPhone(), null, array('phone_validation'));   
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!