【发布时间】:2015-05-22 01:22:51
【问题描述】:
我试图弄清楚如何让数据转换器在收集字段上工作。目前,用户可以创建一个活动并附加最多三个标签。实际上,每次用户为标签输入字符串(它是开放文本输入)时,都会为该标签创建一个新条目,无论它是否已经存在。如果不存在匹配的标签,我想要做的是创建一个新标签,但如果存在,则使用现有标签。
我已经尝试了变压器的各种组合和放置方式,许多似乎都会产生各种错误。我最常看到的:
“对象、数组或空”类型的预期参数,给定“字符串”
我已经通过下面的代码使其进入非错误状态,它确实输出了一个文本字段,但它没有为该字段提供 Campaign 表单的任何属性(ID 或名称)以将其链接起来,因此对我没有好处。
活动实体
/**
* @ORM\Entity
* @ORM\Table(name="campaigns")
*/
class Campaign
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string")
*/
protected $name;
/**
* @var integer
*
* @ORM\Column(name="length", type="integer")
*/
protected $length;
/**
* @var string
*
* @ORM\Column(name="start_date", type="datetime")
*/
protected $startDate;
/* ... snip ... */
/**
* @ORM\ManyToMany(targetEntity="Tag", inversedBy="campaigns", cascade={"persist"})
* @ORM\JoinTable(name="campaigns_tags")
*/
protected $tags;
/* ... snip ... */
标记实体
/**
* @ORM\Entity
* @ORM\Table(name="tags")
*/
class Tag
{
use TimestampTrait;
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var string
*
* @ORM\Column(name="tag", type="string")
*/
protected $tag;
/* ... snip ... */
活动表格
class CampaignFormType extends AbstractType
{
public function __construct(TagFormType $tag_form, SecurityContext $security_context)
{
$this->tag_form = $tag_form;
$this->user = $security_context->getToken()->getUser();
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', 'text', array(
'label' => 'Campaign Name:'
))
->add('length', 'integer', array(
'label' => 'Length (weeks):'
))
->add('startDate', 'date', array(
'label' => 'Start Date:',
'widget' => 'single_text'
))
->add('tags', 'collection', array(
'type' => $this->tag_form,
'allow_add' => TRUE,
'by_reference' => FALSE
));
/* ... snip ... */
标签表单
class TagFormType extends AbstractType
{
/**
* @var EntityManager
*/
private $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new TagToStringTransformer($this->em);
$builder->addModelTransformer($transformer);;
}
public function getParent()
{
return 'text';
}
/* ... snip ... */
标签转换器
class TagToStringTransformer implements DataTransformerInterface
{
/**
* @var EntityManager
*/
private $em;
/**
* @param EntityManager $em
*/
public function __construct(EntityManager $em)
{
$this->em = $em;
}
/**
* @param Tag|null $tag
*
* @return string
*/
public function transform($tag)
{
if (empty($value)) {
return "";
}
return $tag->getTag();
}
/**
* @param string $string
*
* @return Tag|null
*/
public function reverseTransform($string)
{
if (empty($string)) {
return NULL;
}
$tag = $this->em->getRepository('AppBundle:Tag')->findOneBy(array('tag' => $string));
// If the tag doesn't exist, create it
if (empty($tag)) {
$tag = new Tag();
$tag->setTag($string);
}
return $tag;
}
}
更新 我对此进行了更多挖掘,并稍微更改了 TagFormType 使其看起来像下面的代码,并且似乎可以正确输出具有预期名称/id 属性的字段:
class TagFormType extends AbstractType
{
/**
* @var EntityManager
*/
private $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new TagToStringTransformer($this->em);
$builder->add($builder->create('tag', 'text', array('label' => FALSE))->addModelTransformer($transformer));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
array(
'data_class' => 'AppBundle\Entity\Tag',
)
);
}
public function getName()
{
return 'tag';
}
}
【问题讨论】:
-
你能告诉我们你的控制器吗?
-
控制器不处理任何一个,除了创建表单和处理请求对象的两行。编辑:渲染块中的行将表单分配给 twig 变量。
-
你能精确一点你的错误
Expected argument of type "object, array or empty", "string" given吗?你在哪个对象/方法上得到这个? -
@RaphaëlMalié,特别是在我看到该错误的情况下,它会显示为 Tag 实体。但是上面发布的代码并没有发生这种情况,使用该代码我得到了几乎预期的输出,但是输入字段缺少自动生成的 id/name 字段以将它们链接到 Campaign 表单。
-
好吧,我想我明白了,看看
if (empty($value))你没有$valuevar,用$tag替换它;)