Symfony2抛出可捕获的致命错误:无法将类对象转换为字符串

45

我有这个实体定义:

<?php

namespace Apw\BlackbullBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
* Categories
*
* @ORM\Table()
*    @ORM\Entity(repositoryClass="Apw\BlackbullBundle\Entity\CategoriesRepository")
*/
class Categories
{
/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="categories_image", type="string", length=64, nullable = true)
 */
private $categoriesImage;

/**
 * @var integer
 *
 * @ORM\Column(name="parent_id", type="integer", nullable = true, options={"default":0})
 */
private $parentId;

/**
 * @var integer
 *
 * @ORM\Column(name="sort_order", type="integer", nullable = true, options={"default":0})
 */
private $sortOrder;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="date_added", type="datetime", nullable = true)
 */
private $dateAdded;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="last_modified", type="datetime", nullable = true)
 */
private $lastModified;

/**
 * @var boolean
 *
 * @ORM\Column(name="categories_status", type="boolean", nullable = true, options={"default" = 1})
 */
private $categoriesStatus;

/**
 * @ORM\OneToMany(targetEntity="CategoriesDescription", mappedBy="category", cascade={"persist", "remove"})
 */
private $categoryDescription;

/**
 * @ORM\ManyToMany(targetEntity="Products", mappedBy="categories")
 **/
private $products;

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

/**
 * Set categoriesImage
 *
 * @param string $categoriesImage
 * @return Categories
 */
public function setCategoriesImage($categoriesImage)
{
    $this->categoriesImage = $categoriesImage;

    return $this;
}

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

/**
 * Set parentId
 *
 * @param integer $parentId
 * @return Categories
 */
public function setParentId($parentId)
{
    $this->parentId = $parentId;

    return $this;
}

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

/**
 * Set sortOrder
 *
 * @param string $sortOrder
 * @return Categories
 */
public function setSortOrder($sortOrder)
{
    $this->sortOrder = $sortOrder;

    return $this;
}

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

/**
 * Set dateAdded
 *
 * @param \DateTime $dateAdded
 * @return Categories
 */
public function setDateAdded($dateAdded)
{
    $this->dateAdded = $dateAdded;

    return $this;
}

/**
 * Get dateAdded
 *
 * @return \DateTime
 */
public function getDateAdded()
{
    return $this->dateAdded;
}

/**
 * Set lastModified
 *
 * @param \DateTime $lastModified
 * @return Categories
 */
public function setLastModified($lastModified)
{
    $this->lastModified = $lastModified;

    return $this;
}

/**
 * Get lastModified
 *
 * @return \DateTime
 */
public function getLastModified()
{
    return $this->lastModified;
}

/**
 * Constructor
 */
public function __construct()
{
    $this->categoryDescription = new ArrayCollection();
    $this->products = new ArrayCollection();
}

/**
 * Add categoryDescription
 *
 * @param \Apw\BlackbullBundle\Entity\CategoriesDescription $categoryDescription
 * @return Categories
 */
public function addCategoryDescription(\Apw\BlackbullBundle\Entity\CategoriesDescription $categoryDescription)
{
    $this->categoryDescription[] = $categoryDescription;

    return $this;
}

/**
 * Remove categoryDescription
 *
 * @param \Apw\BlackbullBundle\Entity\CategoriesDescription $categoryDescription
 */
public function removeCategoryDescription(\Apw\BlackbullBundle\Entity\CategoriesDescription $categoryDescription)
{
    $this->categoryDescription->removeElement($categoryDescription);
}

/**
 * Get categoryDescription
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getCategoryDescription()
{
    return $this->categoryDescription;
}

/**
 * Add products
 *
 * @param \Apw\BlackbullBundle\Entity\Products $products
 * @return Categories
 */
public function addProduct(\Apw\BlackbullBundle\Entity\Products $products)
{
    $this->products[] = $products;

    return $this;
}

/**
 * Remove products
 *
 * @param \Apw\BlackbullBundle\Entity\Products $products
 */
public function removeProduct(\Apw\BlackbullBundle\Entity\Products $products)
{
    $this->products->removeElement($products);
}

/**
 * Get products
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getProducts()
{
    return $this->products;
}

/**
 * Set categoriesStatus
 *
 * @param boolean $categoriesStatus
 * @return Categories
 */
public function setCategoriesStatus($categoriesStatus)
{
    $this->categoriesStatus = $categoriesStatus;

    return $this;
}

/**
 * Get categoriesStatus
 *
 * @return boolean
 */
public function getCategoriesStatus()
{
    return $this->categoriesStatus;
}
}

然后我在我的控制器中有这个处理表单提交的方法:

<?php

namespace Apw\BlackbullBundle\Controller;


use Apw\BlackbullBundle\Entity\Categories;
use Apw\BlackbullBundle\Entity\CategoriesDescription;
use Apw\BlackbullBundle\Form\CategoriesType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;


class CategoriesController extends Controller
{
   /**
 * @Security("has_role('ROLE_ADMIN')")
 * @Route("/createCategory")
 * @Template()
 */

public function createCategoryAction(Request $request){

    $category = new Categories();
    $categoryDesc = new CategoriesDescription();
    $category->addCategoryDescription($categoryDesc);
    $categoryDesc->setCategory($category);

    $form = $this->createForm(new CategoriesType(), $category);
    $form->handleRequest($request);

    if($form->isValid()){
        //exit(\Doctrine\Common\Util\Debug::dump($category));
        $em = $this->getDoctrine()->getManager();

        $em->persist($category);
        $em->persist($categoryDesc);
        $em->flush();

        return $this->redirect($this->generateUrl('apw_blackbull_categories_showcategories'));
    }

    return array(
        'form' => $form->createView()
    );
}

}

最后,这是我的CategoryType.php:

<?php

namespace Apw\BlackbullBundle\Form;

use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CategoriesType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('categoryDescription', 'collection',
                array(
                    'type' => new CategoriesDescriptionType(),
                    'allow_add' => true,
                    'options' => array('data_class' => 'Apw\BlackbullBundle\Entity\CategoriesDescription'),
                    'by_reference' => false,
                ))
            ->add('categoriesImage', null, array('label'=>'Foto:'))
            ->add('categoriesStatus', null, array('label'=>'Stato:'))
            ->add('parentId', 'entity', array( //provare a mettere una querybuiler
                                            'class'       => 'ApwBlackbullBundle:CategoriesDescription',
                                            'property'    => 'categoriesName',
                                            'empty_value' => 'Scegliere una categoria',
                                            'required'    => false,
                                            'label'       => 'Crea in:'))
            ->add('salva','submit')
            ->add('azzera','reset')
        ;
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Apw\BlackbullBundle\Entity\Categories',
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'categories';
    }
}

当我试图保存数据时,出现了以下错误:

在执行“INSERT INTO Categories(categories_image, parent_id, sort_order, date_added, last_modified, categories_status) VALUES (?, ?, ?, ?, ?, ?)”这个语句时发生异常,其参数为["as", {}, null, null, null, 1]:

Catchable Fatal Error: Object of class Apw\BlackbullBundle\Entity\CategoriesDescription could not be converted to string

我做错了什么?

5个回答

120

你需要在Apw\BlackbullBundle\Entity\CategoriesDescription中实现__toString()方法。

你可以这样做:

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

嗨,CoachNono,我尝试了你的代码,parentId的值是一个对象:object(stdClass)#620 (10) { ["CLASS"]=> string(37) "Apw\BlackbullBundle\Entity\Categories" ["id"]=> NULL ["categoriesImage"]=> string(6) "hp.jpg" ["parentId"]=> object(stdClass)#765 (5) { ["CLASS"]=> string(48) "Apw\BlackbullBundle\Entity\CategoriesDescription" ["id"]=> int(36) ["categoriesName"]=> string(17) "Personal Computer" ["category"]=> string(52) "Proxies__CG__\Apw\BlackbullBundle\Entity\Categories" ["languages"]=> NULL } ["sortOrder"]=> NULL ["dateAdded"]=> NULL ["lastModified"]=> NULL ["categoriesStat... - Falar
这对我起作用了,但是当我编辑一个已经填充了所有数据的表单时,默认情况下下拉菜单不显示保存的选项?我该如何实现呢? - Shairyar
通常情况下,您应该发布一个新问题并在此处链接它,我会查看它。 - Etienne Noël
1
@CoachNono也解决了我的问题!谢谢 :) Symfony 3.1 - Ren
1
这个解决方案解决了我的问题,特别是在Symfony 3.2.5中使用Doctrine的CRUD自动生成视图时遇到的Edit_View。 - JavierFuentes
显示剩余3条评论

12

对于Symfony 3.x:

根据Symfony文档v3.x,您应该使用choice_label属性来指定用于此处的实体字段名称。

->add('categoryDescription', 'collection',
        array(
            'type'         => new CategoriesDescriptionType(),
            'allow_add' => true,
            'options'      => array('data_class' => 'Apw\BlackbullBundle\Entity\CategoriesDescription'),
            'choice_label' => 'name',
            'by_reference' => false,

        ))

太奇怪了,我有一个项目至少运行了6个月,突然开始出现这个错误,在生产服务器上使用choice_label属性解决了问题,尽管该实体具有神奇的toString方法。 - Carlos Delgado

9
我遇到了同样的错误,但我稍微调整了一下,添加了以下内容:
public function __toString() 
{
    return (string) $this->name; 
}

我确定我得到的是 null 而不是字符串值。(我正在使用 sonata-project 工作)


谢谢,我在使用EasyAdmin时遇到了类似的错误,需要使用toString将选择输入生成到表单中。 - Pete_Gore

1

所以我通过在方法$form->isValid()中获取相对父级的值来解决了这个问题。

public function createCategoryAction(Request $request){

        $category = new Categories();
        $categoryDesc = new CategoriesDescription();
        $category->addCategoryDescription($categoryDesc);
        $categoryDesc->setCategory($category);

        $form = $this->createForm(new CategoriesType(), $category);
        $form->handleRequest($request);

        if($form->isValid()){
        //exit(\Doctrine\Common\Util\Debug::dump($parentCategory->getId()));
            $em = $this->getDoctrine()->getManager();
            if(!$category->getParentId()){
                $category->setParentId(0);
            }else{
            // get parent id value from input choice
            $parent = $category->getParentId();
            $parentCategory = $parent->getCategory();
            // end
                $category->setParentId($parentCategory->getId());
            }
            $em->persist($category);
            $em->persist($categoryDesc);
            $em->flush();

            return $this->redirect($this->generateUrl('apw_blackbull_categories_showcategories'));
        }

        return array(
            'form' => $form->createView()
        );
    }

感谢!

你是怎么想到这个解决方案的?我也遇到了一个类似的问题,涉及到控制器和嵌套的一对多关系。当表中有一些行时,它就会出现问题(在数据库为空时运行良好)。所以我猜我的问题和你的类似(通过创建 __toString 来解决,但这感觉像是一个 hack)。知道你是如何得出解决方案的将有助于我解决我的问题! - Benoit Duffez

0
你也可以在你的表单中使用属性访问器:
->add('categoryDescription', 'collection',
            array(
                'type'         => new CategoriesDescriptionType(),
                'allow_add' => true,
                'options'      => array('data_class' => 'Apw\BlackbullBundle\Entity\CategoriesDescription'),
                'by_reference' => false,

            ))

在你的CategoriesDescriptionType中添加'property' => 'name'
顺便说一下,@CoachNono的答案也可以。

嗨,Smashou,我尝试了你的代码,但出现了错误:输入类型的集合中不存在“property”选项。 - Falar
我的错,属性必须在您的CategoriesDescriptionType中。 - Smashou
如果我应用__toString()方法,它不会分配其parentId的值。 - Falar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接