tip*_*ail 2 php forms symfony doctrine-orm
我对 Symfony 相当陌生,但对一般的 PHP Web 开发不太熟悉。也就是说,我很难成功提交“动态”表单。
我一直在关注以下详细信息: http://symfony.com/doc/current/form/dynamic_form_modification.html#form-events-subscribed-data。
我有一个与和实体Profile具有多对一关系的实体。 与 具有 ManyToOne 关系。CountryAreaAreaCountry
在表单上,Area实体选择元素根据Country选择的值动态填充。这工作正常。但是,当我提交表单时,出现以下错误:
Warning: spl_object_hash() expects parameter 1 to be object, integer given
500 Internal Server Error - ContextErrorException。
查看堆栈跟踪,这似乎源于展平我的Area实体选择数组的方法。
感谢任何和所有的帮助 - 到目前为止我已经花了 2 天的时间来研究这个,但我还没有得到更多的帮助!
下面有一些代码细节。如果有更多信息我可以提供,请询问!
谢谢
t2t
我的ProfileType类扩展AbstractType并包含buildForm构建表单的例程。
我里面ProfileType buildForm有以下代码:
// Location Country & Area
// Start: Dynamic form stuff
// http://symfony.com/doc/current/form/dynamic_form_modification.html#form-events-submitted-data
$builder
->add('locationCountry', EntityType::class, [
'class' => 'AppBundle:Country',
'placeholder' => '',
]);
$formModifier = function (FormInterface $form, Country $country = null) {
$arChoices = array();
if (!is_null($country)) {
$arChoices = $this->em->getRepository('AppBundle:Area')->findByCountry($country);
}
$areas = null === $country ? array() : $arChoices;
$form->add('locationArea', EntityType::class, [
'class' => 'AppBundle:Area',
'placeholder' => '',
'choices' => $areas
]);
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
// this would be your entity, i.e. Profile
$data = $event->getData();
$formModifier($event->getForm(), $data->getLocationCountry());
}
);
$builder->get('locationCountry')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$country = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifier($event->getForm()->getParent(), $country);
}
);
// End: Dynamic form stuff
Run Code Online (Sandbox Code Playgroud)
Country定义为:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Country
*
* @ORM\Table(name="Country")
* @ORM\Entity(repositoryClass="AppBundle\Repository\CountryRepository")
*/
class Country
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=100, unique=true)
*/
private $name;
/**
* @var bool
*
* @ORM\Column(name="visible", type="boolean")
*/
private $visible;
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
*
* @return Country
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set visible
*
* @param boolean $visible
*
* @return Country
*/
public function setVisible($visible)
{
$this->visible = $visible;
return $this;
}
/**
* Get visible
*
* @return bool
*/
public function getVisible()
{
return $this->visible;
}
public function __toString() {
return $this->getName();
}
}
Run Code Online (Sandbox Code Playgroud)
Area定义为:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Area
*
* @ORM\Table(name="Area")
* @ORM\Entity(repositoryClass="AppBundle\Repository\AreaRepository")
*/
class Area
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Country")
*/
private $country;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
*
* @return Area
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
public function __toString() {
return $this->name;
}
/**
* Set country
*
* @param \AppBundle\Entity\Country $country
*
* @return Area
*/
public function setCountry(\AppBundle\Entity\Country $country = null)
{
$this->country = $country;
return $this;
}
/**
* Get country
*
* @return \AppBundle\Entity\Country
*/
public function getCountry()
{
return $this->country;
}
}
Run Code Online (Sandbox Code Playgroud)
相关部分Profile定义为:
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Country")
*/
private $locationCountry;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Area")
*/
private $locationArea;
/**
* Set locationArea
*
* @param \AppBundle\Entity\Area $locationArea
*
* @return Profile
*/
public function setLocationArea(\AppBundle\Entity\Area $locationArea = null)
{
$this->locationArea = $locationArea;
return $this;
}
/**
* Get locationArea
*
* @return \AppBundle\Entity\Area
*/
public function getLocationArea()
{
return $this->locationArea;
}
/**
* Set locationCountry
*
* @param \AppBundle\Entity\Country $locationCountry
*
* @return Profile
*/
public function setLocationCountry(\AppBundle\Entity\Country $locationCountry = null)
{
$this->locationCountry = $locationCountry;
return $this;
}
/**
* Get locationCountry
*
* @return \AppBundle\Entity\Country
*/
public function getLocationCountry()
{
return $this->locationCountry;
}
Run Code Online (Sandbox Code Playgroud)
最后,在我的AreaRepository我有以下内容:
namespace AppBundle\Repository;
use AppBundle\Entity\Area;
/**
* AreaRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class AreaRepository extends \Doctrine\ORM\EntityRepository
{
/**
* @param $oCountry
* @return array
*/
public function findByCountry($oCountry) {
if (is_null($oCountry)) {
return array();
}
$oRepo = $this->getEntityManager()->getRepository('AppBundle:Area');
$oQB = $oRepo->createQueryBuilder('a');
$oQuery = $oQB->where('a.country = :countryId')
->setParameter('countryId', $oCountry)
->getQuery();
$arResult = $oQuery->getArrayResult();
return $arResult;
}
}
Run Code Online (Sandbox Code Playgroud)
您收到此错误是因为为了持久性而传递的是对象的 id 而不是对象本身。
看看你自己的评论:$event->getData() will get you the client data (that is, the ID)
所以你将对象的 id 传递给你的$formModifier函数。
事情在这条线上失败了
$arChoices = $this->em->getRepository('AppBundle:Area')->findByCountry($country);
当您将检索到的 id 传递给 findByCountry 时。
底线:你应该传递一个国家对象,而不仅仅是它的 id。