【问题标题】:Symfony Form with Doctrine Entity - Relation not loading for editing带有教义实体的 Symfony 表单 - 未加载关系以进行编辑
【发布时间】:2016-08-31 13:46:47
【问题描述】:

我遇到了一些我认为可能是相当基本的问题,但原因却让我无法理解。

我有两个实体,一个组织和一个订阅。一个组织与一个订阅相关联。

我希望能够通过表单进行编辑(通过表单创建已经可以)。当我执行以下操作时:

    $organisation = $this->getDoctrine()->getRepository('AppBundle\Entity\Organisation')
        ->findOneBy(array(
            'id' => $id
        ));

    $form = $this->createForm(new OrganisationType(), $organisation, array(
        'method' => 'POST'
    ));

    $form->submit($paramFetcher->all());

我收到一个异常,因为未设置组织实体的订阅属性(尽管将订阅属性传递给表单默认值)。例外情况如下:

Expected argument of type "AppBundle\Entity\Subscription", "NULL" given

这显然是由组织实体上的 setSubscription 方法抛出的,但我不确定为什么表单应该自动转换传递给订阅实体的 int 值。

我在这里做傻事吗?我在下面附上了相关代码。谢谢!

复制此问题的最简单控制器操作

public function testAction(Request $request)
{

    $organisation = $this->getDoctrine()->getRepository('AppBundle\Entity\Organisation')
        ->findOneBy(array('id' => 7));

    $form = $this->createForm(new OrganisationType(), $organisation);

    $form->submit($request->request->all());

    return $this->render('test.html.twig', array(
        'testform' => $form->createView()
    ));

}

Organisation.php

<?php

namespace AppBundle\Entity;

use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * Organisation
 *
 * @ORM\Table(name="organisation")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\OrganisationRepository")
 */
class Organisation
{

const ENABLED = 1;
const DISABLED = 2;

/**
 * @var int
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 * @JMS\Groups({"default", "list-organisation"})
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="name", type="string", length=255)
 * @JMS\Groups({"default", "list-organisation"})
 */
private $name;

/**
 * @var Subscription|null The subscription this organisation is currently linked to
 * @ORM\ManyToOne(targetEntity="Subscription", inversedBy="organisations")
 * @ORM\JoinColumn(name="subscription_id", referencedColumnName="id", onDelete="set null")
 * @JMS\Groups({"default", "list-organisation"})
 */
private $subscription;

/**
 * @var Collection
 * @ORM\OneToMany(targetEntity="User", mappedBy="organisation")
 * @JMS\Groups({})
 */
private $users;

/**
 * @var Collection
 * @ORM\OneToMany(targetEntity="Subgroup", mappedBy="organisation")
 * @JMS\Groups({"default"})
 */
private $subgroups;

/**
 * @var string $enabled
 *
 * @ORM\Column(type="string")
 */
private $enabled = self::ENABLED;

/**
 * @var datetime $created
 *
 * @Gedmo\Timestampable(on="create")
 * @ORM\Column(type="datetime")
 * @JMS\Groups({"default", "list-organisation"})
 */
private $created;

/**
 * @var datetime $updated
 *
 * @Gedmo\Timestampable(on="update")
 * @ORM\Column(type="datetime")
 * @JMS\Groups({"default", "list-organisation"})
 */
private $updated;

/**
 * Get id
 *
 * @return integer 
 */
public function getId()
{
    return $this->id;
}

/**
 * Set name
 *
 * @param string $name
 * @return Organisation
 */
public function setName($name)
{
    $this->name = $name;

    return $this;
}

/**
 * Sets subscription
 *
 * @param Subscription $subscription
 * @return $this
 */
public function setSubscription(Subscription $subscription)
{
    $this->subscription = $subscription;

    return $this;
}

/**
 * Gets subscription
 *
 * @return Subscription|null
 */
public function getSubscription()
{
    return $this->subscription;
}

/**
 * Sets enabled
 *
 * @param $enabled
 */
public function setEnabled($enabled)
{
    if (!in_array($enabled, array(self::ENABLED, self::DISABLED))) {
        throw new \InvalidArgumentException('Invalid enabled status');
    }

    $this->enabled = $enabled;
}

/**
 * Gets enabled
 *
 * @return string
 */
public function getEnabled()
{
    return $this->enabled;
}

/**
 * Get name
 *
 * @return string 
 */
public function getName()
{
    return $this->name;
}

/**
 * Returns Users belonging to this organisation
 *
 * @return Collection
 */
public function getUsers()
{
    return $this->users;
}

public function __toString()
{
    return $this->getName();
}
}

Subscription.php

<?php

namespace AppBundle\Entity;

use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;
use Gedmo\Mapping\Annotation as Gedmo;

/**
 * Organisation
 *
 * @ORM\Table(name="subscription")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\SubscriptionRepository")
 */
class Subscription
{
/**
 * @var int
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 * @JMS\Groups({"default", "list-organisation"})
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="name", type="string", length=255)
 * @JMS\Groups({"default", "list-organisation"})
 */
private $name;

/**
 * @var Collection
 * @ORM\OneToMany(targetEntity="Organisation", mappedBy="subscription")
 * @JMS\Groups({"default"})
 */
private $organisations;

/**
 * @var datetime $created
 *
 * @Gedmo\Timestampable(on="create")
 * @ORM\Column(type="datetime")
 * @JMS\Groups({"default"})
 */
private $created;

/**
 * @var datetime $updated
 *
 * @Gedmo\Timestampable(on="update")
 * @ORM\Column(type="datetime")
 * @JMS\Groups({"default"})
 */
private $updated;

/**
 * Get id
 *
 * @return integer 
 */
public function getId()
{
    return $this->id;
}

/**
 * Set name
 *
 * @param string $name
 * @return Subscription
 */
public function setName($name)
{
    $this->name = $name;

    return $this;
}

/**
 * Get name
 *
 * @return string 
 */
public function getName()
{
    return $this->name;
}

/**
 * Returns Organisations with this subscription type
 *
 * @return Collection
 */
public function getOrganisations()
{
    return $this->organisations;
}

/**
 * @return string
 */
public function __toString()
{
    return $this->getName();
}
}

OrganisationType.php

<?php

namespace AppBundle\Form;

use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class OrganisationType extends AbstractType
{
private $manager;

public function __construct(ObjectManager $objectManager)
{
    $this->manager = $objectManager;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('name');
    $builder->add('subscription', EntityType::class, array(
        'class' => 'AppBundle\Entity\Subscription'
    ));

}

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'AppBundle\Entity\Organisation',
        'csrf_protection' => false
    ));
}
}

【问题讨论】:

  • 首先,为什么要在该实体字段上使用 DataTransformer ? Symfony 本身就能够将整数(由表单的选择字段提供)转换为对象,只要您提供要使用的类,就像您在字段选项中所做的那样。其次,你能提供抛出的异常吗?
  • @VaN 你好,我把变压器放进去只是为了检查它是否正在转换。这是不必要的,我已经删除了它。我已经编辑了我的帖子以显示实际的异常。谢谢你的帮助,这个让我发疯了!
  • 我唯一不熟悉的是你处理表单提交的方式。我从未使用过$form-&gt;submit($paramFetcher-&gt;all())。根据文档,处理表单的方式如下:$form-&gt;handleRequest($request); if ($form-&gt;isSubmitted() &amp;&amp; $form-&gt;isValid()) { $organisation = $form-&gt;getData(); // ... perform some action, such as saving the task to the databasesymfony.com/doc/current/forms.html#handling-form-submissions
  • 嗨@VaN,有趣的是,使用handleRequest 实际上并没有为我提交表单。如果我使用它然后调用isValid,则表单的行为就像尚未提交一样。文档中建议使用$form-&gt;submit($paramFetcher-&gt;all()) 直接提交表单。我敢肯定我在这里遗漏了一些非常愚蠢的东西,但我就是看不到它。
  • 你能发布你的整个控制器动作吗?你用的是哪个版本的 symfony2?

标签: php symfony doctrine-orm symfony-forms


【解决方案1】:

在新的 Symfony 3.1 上,这就像一个魅力(这是处理表单提交的推荐方式,如前一条评论所述):

public function testAction(Request $request)
{
    $organisation = $this->getDoctrine()->getRepository('AppBundle\Entity\Organisation')
        ->find(1);

    $form = $this->createForm(OrganisationType::class, $organisation);

    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $this->getDoctrine()->getManager()->persist($organisation);
        $this->getDoctrine()->getManager()->flush();

        die('saved into database.');
    }

    return $this->render('test.html.twig', array(
        'testform' => $form->createView()
    ));

}

【讨论】:

  • 非常感谢您的努力。我还没有找到它的来源,尽管我怀疑它可能与序列化组或其他东西有关。我暂时不得不继续前进,但当我重新开始时,我会用答案更新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-28
  • 2014-06-08
  • 2018-08-31
  • 1970-01-01
  • 1970-01-01
  • 2019-11-04
  • 2016-03-21
相关资源
最近更新 更多