【发布时间】: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->submit($paramFetcher->all())。根据文档,处理表单的方式如下:$form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $organisation = $form->getData(); // ... perform some action, such as saving the task to the database见symfony.com/doc/current/forms.html#handling-form-submissions -
嗨@VaN,有趣的是,使用handleRequest 实际上并没有为我提交表单。如果我使用它然后调用
isValid,则表单的行为就像尚未提交一样。文档中建议使用$form->submit($paramFetcher->all())直接提交表单。我敢肯定我在这里遗漏了一些非常愚蠢的东西,但我就是看不到它。 -
你能发布你的整个控制器动作吗?你用的是哪个版本的 symfony2?
标签: php symfony doctrine-orm symfony-forms