[英]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: 细节:
simple_array
: http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/types.html#simple-array 我的实体是simple_array
类型: http : simple_array
$builder->add('emails', EmailType::class, array('attr'=>array('multiple'=>'multiple')));
<input type="email" multiple="multiple">
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.