带有条令实体的Symfony表单-关系不能加载用于编辑


Symfony Form with Doctrine Entity - Relation not loading for editing

我有一个问题,我认为可能是相当基本的,但原因是逃避我。

我有两个实体,一个组织和一个订阅。一个组织与一个订阅链接在一起。

我想能够编辑这通过一个表单(创建通过表单已经工作)。当我执行以下操作时:

    $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
    ));
}
}

在新的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()
    ));
}