Symfony2 将自定义字段添加到表单构建器
Posted
技术标签:
【中文标题】Symfony2 将自定义字段添加到表单构建器【英文标题】:Symfony2 add custom field to form builder 【发布时间】:2014-11-10 18:53:59 【问题描述】:我有一个实体事件,它有一个字段关键字,它是一对多映射到另一个实体事件关键字。我还有一个表单类型类 CreateEventFormType。我使用以下代码在我的控制器中创建表单:
$event = new Event();
$form = $this->createForm(new CreateEventFormType(), $event);
但我还需要用于创建对象 EventKeywords 的关键字的附加输入字段。我尝试将其添加到我的 formBuilderInterface:
->add('keywords', 'text', [
'constraints' =>[
new Assert\NotBlank([
'message' => "Renginio raktažodžiai negali būti tušti"
]),
new Assert\Length([
'min' => "2",
'max' => "255",
'minMessage' => "Renginio raktažodžiai negali būti trumpesni nei limit simboliai",
'maxMessage' => "Renginio raktažodžiai negali būti ilgesni nei limit simboliai"
])
]
])
然后我得到错误
Neither the property "keywords" nor one of the methods "addKeyword()"/"removeKeyword()", "setKeywords()", "keywords()", "__set()" or "__call()" exist and have public access in class "Atotrukis\MainBundle\Entity\Event".
完整的实体和FormType代码:
createEventFormType.php
<?php
namespace Atotrukis\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Validator\Constraints as Assert;
class CreateEventFormType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options)
$builder
->add('name', 'text', [
'constraints' =>[
new Assert\NotBlank([
'message' => "Renginio pavadinimas negali būti tuščias"
]),
new Assert\Length([
'min' => "2",
'max' => "255",
'minMessage' => "Renginio pavadinimas negali būti trumpesnis nei limit simboliai",
'maxMessage' => "Renginio pavadinimas negali būti ilgesnis nei limit simboliai"
])
]
])
->add('description', 'textarea', [
'constraints' =>[
new Assert\NotBlank([
'message' => "Renginio aprašymas negali būti tuščias"
]),
new Assert\Length([
'min' => "10",
'max' => "5000",
'minMessage' => "Renginio aprašymas negali būti trumpesnis nei limit simbolių",
'maxMessage' => "Renginio aprašymas negali būti ilgesnis nei limit simbolių"
])
]
])
->add('startDate', 'datetime', [
'constraints' =>[
new \Atotrukis\MainBundle\Validator\Constraints\FutureDateTime([
'message' => "Pradžios laikas negali būti ankstesnis už dabartinį laiką."
])
]
])
->add('endDate', 'datetime', [
'constraints' =>[
new \Atotrukis\MainBundle\Validator\Constraints\FutureDateTime([
'message' => "Pabaigos laikas negali būti ankstesnis už dabartinį laiką."
])
]
])
->add('keywords', 'text', [
'constraints' =>[
new Assert\NotBlank([
'message' => "Renginio raktažodžiai negali būti tušti"
]),
new Assert\Length([
'min' => "2",
'max' => "255",
'minMessage' => "Renginio raktažodžiai negali būti trumpesni nei limit simboliai",
'maxMessage' => "Renginio raktažodžiai negali būti ilgesni nei limit simboliai"
])
]
])
->add('map', 'hidden')
->add('city', 'entity', array(
'class' => 'AtotrukisMainBundle:City',
'property' => 'name',
'constraints' =>[
new Assert\NotBlank([
'message' => "Privalote pasirinkti miestą"
])
],
'empty_value' => 'Pasirinkite miestą',
'query_builder' => function(EntityRepository $er)
return $er->createQueryBuilder('c')
->addOrderBy('c.priority', 'ASC')
->addOrderBy('c.name', 'ASC');
,
));
// ->add('save', 'submit', array('label' => 'Sukurti'));
public function getName()
return 'createEventForm';
事件.php
<?php
namespace Atotrukis\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Atotrukis\MainBundle\Validator\Constraints as CustomAssert;
/**
* @ORM\Entity
* @ORM\Table(name="events")
* @CustomAssert\DateRange
*/
class Event
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string", length=255)
*/
protected $name;
/**
* @ORM\Column(type="text")
*/
protected $description;
/**
* @ORM\Column(type="datetime")
*/
protected $startDate;
/**
* @ORM\Column(type="datetime")
*/
protected $endDate;
/**
* @ORM\ManyToOne(targetEntity="User", inversedBy="events")
* @ORM\JoinColumn(name="createdBy", referencedColumnName="id")
*/
protected $createdBy;
/**
* @ORM\Column(type="datetime")
*/
protected $createdOn;
/**
* @ORM\Column(type="string", length=2083)
*/
protected $map;
/**
* @ORM\OneToMany(targetEntity="EventPhoto", mappedBy="eventId")
*/
protected $photos;
/**
* @ORM\OneToMany(targetEntity="UserAttending", mappedBy="eventId")
*/
protected $usersAttending;
/**
* @ORM\OneToMany(targetEntity="EventKeywords", mappedBy="eventId")
*/
protected $keywords;
/**
* @ORM\ManyToOne(targetEntity="City", inversedBy="eventId")
* @ORM\JoinColumn(name="city", referencedColumnName="id")
*/
protected $city;
public function __construct()
$this->createdOn = new \DateTime();
$this->keywords = new ArrayCollection();
//parent::__construct();
/**
* Get id
*
* @return integer
*/
public function getId()
return $this->id;
/**
* Set name
*
* @param string $name
* @return Event
*/
public function setName($name)
$this->name = $name;
return $this;
/**
* Get name
*
* @return string
*/
public function getName()
return $this->name;
/**
* Set description
*
* @param string $description
* @return Event
*/
public function setDescription($description)
$this->description = $description;
return $this;
/**
* Get description
*
* @return string
*/
public function getDescription()
return $this->description;
/**
* Set startDate
*
* @param \DateTime $startDate
* @return Event
*/
public function setStartDate($startDate)
$this->startDate = $startDate;
return $this;
/**
* Get startDate
*
* @return \DateTime
*/
public function getStartDate()
return $this->startDate;
/**
* Set endDate
*
* @param \DateTime $endDate
* @return Event
*/
public function setEndDate($endDate)
$this->endDate = $endDate;
return $this;
/**
* Get endDate
*
* @return \DateTime
*/
public function getEndDate()
return $this->endDate;
/**
* Set createdBy
*
* @param integer $createdBy
* @return Event
*/
public function setCreatedBy($createdBy)
$this->createdBy = $createdBy;
return $this;
/**
* Get createdBy
*
* @return integer
*/
public function getCreatedBy()
return $this->createdBy;
/**
* Set createdOn
*
* @param \DateTime $createdOn
* @return Event
*/
public function setCreatedOn($createdOn)
$this->createdOn = $createdOn;
return $this;
/**
* Get createdOn
*
* @return \DateTime
*/
public function getCreatedOn()
return $this->createdOn;
/**
* Add photos
*
* @param \Atotrukis\MainBundle\Entity\EventPhoto $photos
* @return Event
*/
public function addPhoto(\Atotrukis\MainBundle\Entity\EventPhoto $photos)
$this->photos[] = $photos;
return $this;
/**
* Remove photos
*
* @param \Atotrukis\MainBundle\Entity\EventPhoto $photos
*/
public function removePhoto(\Atotrukis\MainBundle\Entity\EventPhoto $photos)
$this->photos->removeElement($photos);
/**
* Get photos
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getPhotos()
return $this->photos;
/**
* Set map
*
* @param string $map
* @return Event
*/
public function setMap($map)
$this->map = $map;
return $this;
/**
* Get map
*
* @return string
*/
public function getMap()
return $this->map;
/**
* Set city
*
* @param \Atotrukis\MainBundle\Entity\City $city
* @return Event
*/
public function setCity(\Atotrukis\MainBundle\Entity\City $city = null)
$this->city = $city;
return $this;
/**
* Get city
*
* @return \Atotrukis\MainBundle\Entity\City
*/
public function getCity()
return $this->city;
/**
* Add usersAttending
*
* @param \Atotrukis\MainBundle\Entity\UserAttending $usersAttending
* @return Event
*/
public function addUsersAttending(\Atotrukis\MainBundle\Entity\UserAttending $usersAttending)
$this->usersAttending[] = $usersAttending;
return $this;
/**
* Remove usersAttending
*
* @param \Atotrukis\MainBundle\Entity\UserAttending $usersAttending
*/
public function removeUsersAttending(\Atotrukis\MainBundle\Entity\UserAttending $usersAttending)
$this->usersAttending->removeElement($usersAttending);
/**
* Get usersAttending
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getUsersAttending()
return $this->usersAttending;
/**
* Add keywords
*
* @param \Atotrukis\MainBundle\Entity\EventKeywords $keywords
* @return Event
*/
public function addKeyword(\Atotrukis\MainBundle\Entity\EventKeywords $keywords)
$this->keywords[] = $keywords;
return $this;
/**
* Remove keywords
*
* @param \Atotrukis\MainBundle\Entity\EventKeywords $keywords
*/
public function removeKeyword(\Atotrukis\MainBundle\Entity\EventKeywords $keywords)
$this->keywords->removeElement($keywords);
/**
* Get keywords
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getKeywords()
return $this->keywords;
/**
* Set keywords
*
* @param \Atotrukis\MainBundle\Entity\EventKeywords $keywords
* @return Event
*/
public function setKeywords(\Atotrukis\MainBundle\Entity\EventKeywords $keywords = null)
$this->keywords = $keywords;
return $this;
EventKeywords.php
<?php
namespace Atotrukis\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="event_keywords")
*/
class EventKeywords
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string", length=255)
*/
protected $keyword;
/**
* @ORM\ManyToOne(targetEntity="Event", inversedBy="keywords")
* @ORM\JoinColumn(name="eventId", referencedColumnName="id")
*/
protected $eventId;
/**
* Get id
*
* @return integer
*/
public function getId()
return $this->id;
/**
* Set eventId
*
* @param \Atotrukis\MainBundle\Entity\Event $eventId
* @return UserAttending
*/
public function setEventId(\Atotrukis\MainBundle\Entity\Event $eventId = null)
$this->eventId = $eventId;
return $this;
/**
* Get eventId
*
* @return \Atotrukis\MainBundle\Entity\Event
*/
public function getEventId()
return $this->eventId;
/**
* Set keyword
*
* @param string $keyword
* @return EventKeywords
*/
public function setKeyword($keyword)
$this->keyword = $keyword;
return $this;
/**
* Get keyword
*
* @return string
*/
public function getKeyword()
return $this->keyword;
【问题讨论】:
事件实体中的关键字设置器在哪里?我找不到它.. 你也应该初始化keywords
集合(在__construct
和ArrayCollection
中)
我已将关键字设置器添加到事件实体。还尝试将 $this->keywords = new ArrayCollection();
添加到 __construct 但现在出现错误:Catchable Fatal Error: Argument 1 passed to Atotrukis\MainBundle\Entity\Event::setKeywords() must be an instance of Atotrukis\MainBundle\Entity\EventKeywords, string given, called in /var/www/vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php on line 438 and defined in /var/www/src/Atotrukis/MainBundle/Entity/Event.php line 389
1.我看到您添加了setKeyWords
,但没有看到集合初始化。 2. 由于您设置了 OneToMany 关联,该字段应该包含对象集合,而不是单个 EventKeywords
对象
我该怎么做?我对 Symfony 和 OOP 都很陌生。
【参考方案1】:
你要做的是:
->add('yourfield', 'choice', array(
'label' => 'Your Field',
'required' => false,
'choices' => array(true => 'Yes', false => 'No'),
'empty_value' => false,
'mapped' => false
))
注意 'mapped' => false 。这意味着该字段与您的 entity(object) 无关。它根本不存在于您的班级中。 这样做,您将能够添加任意数量的附加字段。
【讨论】:
以上是关于Symfony2 将自定义字段添加到表单构建器的主要内容,如果未能解决你的问题,请参考以下文章
将自定义参数传递给 Symfony2 中的自定义 ValidationConstraint
Drupal,Ubercart - 将自定义字段添加到结帐表单
Symfony2 表单 > 实体字段类型 > 查询构建器 > 可能的子选择?