简体   繁体   English

Symfony2 Forms&Doctrine:将带有多个地址的EmailType保存到simple_array中

[英]Symfony2 Forms & Doctrine: Persist EmailType with multiple addresses into simple_array

It looks like there is no direct way to save the outcome of <input type="email" multiple> into Doctrine's simple_array field, through Symfony 2 forms. 看起来没有直接的方法可以通过Symfony 2表单将<input type="email" multiple>的结果保存到Doctrine的simple_array字段中。

Details: 细节:

Now, when I enter two email addresses in the form (comma-separated, as expected by HTML5), the entity receives a comma-separated string . 现在,当我在表单中输入两个电子邮件地址(以逗号分隔,如HTML5所预期的那样)时,实体会收到逗号分隔的字符串

However, when persisting into the simple_array field, Doctrine expects an array , onto which it calls implode() . 但是,当持久化到simple_array字段时,Doctrine需要一个数组 ,它调用implode()

So the error message I get is: Warning: implode(): Invalid arguments passed 所以我得到的错误信息是: Warning: implode(): Invalid arguments passed

Reason: Symfony doesn't explode the comma-separated string into an array, before handing it over to Doctrine. 原因:在将其交给Doctrine之前,Symfony不会将逗号分隔的字符串分解为数组。

Solution: Do it manually: 解决方案:手动执行:
$entity->setEmails(explode(',', $entity->getEmails()));

So finally my question is: Is there an easier way for this? 所以最后我的问题是:这有更简单的方法吗?

I can suggest model transformer for this form field. 我可以为这个表格字段建议模型变换器。 Transformer will convert value from array to string for form and from string to array for doctrine. Transformer会将值从数组转换为字符串表单,从字符串转换为数组作为教义。

http://symfony.com/doc/current/form/data_transformers.html http://symfony.com/doc/current/form/data_transformers.html

$builder->add('emails', EmailType::class, array('attr'=>array('multiple'=>'multiple')));

$builder->get('emails')
    ->addModelTransformer(new \Symfony\Component\Form\CallbackTransformer(
        function ($original) {
            return implode(',', $original);
        },
        function ($submitted) {
            return explode(',', $submitted);
        }
    ))
;

Maybe you can do it inside the setter of the Entity, by testing if the parameter given is a string or an array 也许你可以在实体的setter中做,通过测试给定的参数是字符串还是数组

public function setEmails($emails)
{
    if (is_string($emails)) {
        $emails = explode(',', $emails);
    }

    $this->emails = $emails;
}

After the answers of @Max P. and @jeremy: 在@Max P.和@jeremy的答案之后:

Both methods work in principle! 两种方法原则上都有效! However, they break validation (see comments). 但是,它们会破坏验证(请参阅注释)。

So here's what I finally came up with to enable validation: 所以这就是我最终提出的启用验证的方法:

Following http://symfony.com/doc/current/validation/custom_constraint.html 关注http://symfony.com/doc/current/validation/custom_constraint.html

// src/AppBundle/Validator/Constraints/Array255Validator.php 
class Array255Validator extends ConstraintValidator
{
    public function validate($value, Constraint $constraint)
    {
        $string = implode(',', $value);
        if (strlen($string) > 255) {
            $this->context->buildViolation($constraint->message)
                ->setParameter('%string%', $string) // use $string here, since $value is an array!
                ->addViolation();
        }
    }
}

You can even apply validation to each array element, by using the All constraint: http://symfony.com/doc/current/reference/constraints/All.html 您甚至可以使用All约束对每个数组元素应用验证: http//symfony.com/doc/current/reference/constraints/All.html

properties:
    email:
        - AppBundle\Validator\Constraints\Array255: ~
        - All:
            - NotBlank:  ~
            - Length:
                min: 5
            - Email:
                checkMX: true
                message: "Some message for {{ value }}"

Thanks!! 谢谢!!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM