Symfony 3 spl_object_hash 期望参数 1 是对象,提交表单时给出的整数

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)

Maw*_*cel 6

您收到此错误是因为为了持久性而传递的是对象的 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。