一个简单的问题,在SO上有很多答案......但是它们都没有在我的项目上工作......所以我得到了这个错误:
ContextErrorException: Catchable Fatal Error: Argument 1 passed to Doctrine\Common\Collections\ArrayCollection::__construct() must be of the type array, object given, called in C:\wamp\www\Dig\front\vendor\doctrine\orm\lib\Doctrine\ORM\UnitOfWork.php on line 528 and defined in C:\wamp\www\Digidis\front\vendor\doctrine\collections\lib\Doctrine\Common\Collections\ArrayCollection.php line 48
每次创建新电子邮件并尝试将其保存在数据库中时都会发生这种情况。电子邮件与皮肤有关系..
这是我尝试保存它的方式:
/**
* @Route("/{skin_id}/new", name="cms_email_new")
* @Method({"GET"})
* @Template()
*/
public function newAction($skin_id) {
$skin = $this->getRepository('ProjectSkinBundle:Skin')->find($skin_id);
$item = new Email();
$form = $this->createForm(new EmailType($this->container->getParameter("langs")), $item);
return array('form' => $form->createView(), 'item' => $item, 'skin' => $skin_id);
}
/**
* @Route("/{skin_id}/save", name="cms_email_save")
* @Template("ProjectUserBundle:EmailAdmin:new.html.twig")
* @Method({"POST"})
*/
public function saveAction(Request $request, $skin_id) {
$skin = $this->getRepository('ProjectSkinBundle:Skin')->find($skin_id);
$item = new Email();
$type = new EmailType($this->container->getParameter("langs"));
$form = $this->createForm($type, $item);
$form->handleRequest($request);
$em = $this->getEntityManager();
if ($form->isValid()) {
$this->upload($form, $item);
$skin->setEmailId($item);
$item->setSkin($skin); /// the error is here
$em->persist($skin);
$em->persist($item);
$em->flush();
return $this->redirect($this->generateUrl('cms_skin_email_edit', array('skin_id' => $skin_id)));
}
return array('form' => $form->createView(), 'item' => $item);
}
因此,通过一些测试我发现这一行导致了问题:
$item->setSkin($skin);
如果没有这条线,一切都像魅力一样。但是我需要这条线才能工作。
所以这是带有setSkin方法的实体:
/**
*
* @ORM\OneToMany(targetEntity="Project\SkinBundle\Entity\Skin", mappedBy="email_id")
* @ORM\JoinColumn(name="skin", referencedColumnName="id")
*/
protected $skin;
/**
* Set skin
*
* @param \Project\SkinBundle\Entity\Skin $skin
* @return Email
*/
public function setSkin(\Project\SkinBundle\Entity\Skin $skin = null)
{
$this->skin = $skin;
return $this;
}
/**
* Get skin
*
* @return \Project\SkinBundle\Entity\Skin
*/
public function getSkin()
{
return $this->skin;
}
那么我该怎样做才能使他的对象成为一个数组?
我有这条小行但是id并没有帮助我:
public function __construct()
{
$this->skin = new ArrayCollection();
}
创建新电子邮件的表单是:
public function buildForm(FormBuilderInterface $builder, array $option) {
$builder->add('title', 'text', array('label' => 'cms.Title'));
}
public function getDefaultOptions(array $options) {
return array(
'data_class' => 'Project\UserBundle\Entity\Email',
);
}
public function getName()
{
return 'my_email';
}
}
答案 0 :(得分:0)
$skin
属性是您的学说映射中的一对多关系。 Doctrine期待一个ArrayCollection
对象或数组。
这导致您的例外:
/**
*
* @ORM\OneToMany(targetEntity="Project\SkinBundle\Entity\Skin", mappedBy="email_id")
* @ORM\JoinColumn(name="skin", referencedColumnName="id")
*/
protected $skin;
如果您需要一对多关系,则应传递array
而不是单个对象,因为您可以拥有多个皮肤。如果你想要一对一的关系(每个实体一个皮肤),你应该改变你的学说映射。
可能的解决方案1:
public function __construct()
{
$this->skin = new ArrayCollection();
}
/**
* Set skin
*
* @param \Project\SkinBundle\Entity\Skin $skin
* @return Email
*/
public function setSkin(array $skin)
{
$this->skin = $skin;
return $this;
}
/**
* Get skin
*
* @return \Project\SkinBundle\Entity\Skin[]|ArrayCollection
*/
public function getSkin()
{
return $this->skin;
}
可能的解决方案2(OneToOne,但这可能是一个ManyToOne,这取决于你):
/**
*
* @ORM\OneToOne(targetEntity="Project\SkinBundle\Entity\Skin", mappedBy="email_id")
* @ORM\JoinColumn(name="skin", referencedColumnName="id")
*/
protected $skin;
答案 1 :(得分:0)
您可以通过简单地将对象(您应该确认的是“电子邮件”对象)包装在数组中来防止错误:
$item->setSkin(array($skin));
然而这里出现了其他问题,错误来自于Doctrine编译工作单元以保存到数据库时。
电子邮件实体的皮肤关系声明不正确。 Join列声明应位于manyToOne一侧,因此Email应为:
电子邮件实体:
/*
* @ORM\OneToMany(targetEntity="Project\SkinBundle\Entity\Skin", mappedBy="email")
*/
protected $skins;
皮肤实体:
/*
* @ORM\ManyToOne(targetEntity="Project\SkinBundle\Entity\Email", inversedBy="emails")
* @ORM\JoinColumn(name="email_id", referencedColumnName="id")
*/
protected $email
然后运行app/console doctrine:generate:entities SkinBundle:Email
(或引用实体)将生成类似addSkin(Skin $skin)
的方法,用于向对象添加对象。
可在Doctrine associations找到更多信息。
答案 2 :(得分:0)
对于一对多关系,您应该使用方法addSkin()和removeSkin()代替setSkin()。此外,作为惯例,我建议复数收集属性,即$ skin - > $皮肤。它使代码更清晰,声明和使用实体的错误变得更加明显。
因此,对于您的实体,我建议使用许多$皮肤:
/**
* @var \Doctrine\Common\Collections\Collection
*/
private $skins;
/**
* Constructor
*/
public function __construct()
{
$this->skins = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add skin
*
* @param Skin $skin
* @return Email
*/
public function addSkin(Skin $skin)
{
$this->skins[] = $skin;
return $this;
}
/**
* Remove skin
*
* @param Skin $skin
*/
public function removeSkin(Skin $skin)
{
$this->skins->removeElement($skin);
}
/**
* Get skins
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getSkins()
{
return $this->skins;
}
然后你在哪里:
$item->setSkin($skin);
您应该使用:
$item->addSkin($skin);