45

I have this Entity defined:

<?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;
}
}

Then I have this method in my controller for handle form submission:

<?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()
    );
}

}

And finally this is my 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';
    }
}

When I try to save data I get this error:

An exception occurred while executing 'INSERT INTO Categories (categories_image, parent_id, sort_order, date_added, last_modified, categories_status) VALUES (?, ?, ?, ?, ?, ?)' with params ["as", {}, null, null, null, 1]:

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

What I'm doing wrong?

Falar
  • 519
  • 2
  • 5
  • 10

5 Answers5

119

You need to implement the __toString() method in your Apw\BlackbullBundle\Entity\CategoriesDescription.

You could do:

public function __toString() {
    return $this->name;
}
Etienne Noël
  • 5,988
  • 6
  • 48
  • 75
  • Hi CoachNono i tried your code and the value of parentId is an abject: 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 Feb 25 '15 at 11:34
  • This worked for me, however when i am editing a form where all the data is pre-filled the dropdown menu does not show the saved option by default? how can i achieve that – Shairyar Jun 30 '15 at 11:46
  • Normally it should, post a new question and link it in here and I'll take a look at it – Etienne Noël Jun 30 '15 at 11:56
  • 1
    @CoachNono Also solved my problem! Thanks :) Symfony 3.1 – Ren Aug 21 '16 at 17:59
  • 1
    This solution has solved my problem with **Doctrine's CRUD auto-generated Views**, in particular with **Edit_View** in Symfony 3.2.5 – JavierFuentes May 01 '17 at 20:18
  • This leads to an error on form submit. Only the string value without any reference to the original entity is submitted. Doesn't work for me. – Tim Wißmann Apr 10 '19 at 22:42
  • Can you explain, why we need `__toString()`? – peace_love Oct 21 '19 at 15:02
  • @peace_love It's been a while, but I think it's because Symfony doesn't know how to insert the value into the database since it's a collection and doesn't know how to serialize a collection into a database row but I might be wrong. – Etienne Noël Jul 15 '20 at 18:49
12

For Symfony 3.x

According with Symfony docs v3.x you should use choice_label property to specify the entity field name to be used here.

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

        ))
Giovani
  • 2,459
  • 1
  • 21
  • 16
  • That's so weird, i had a project running for at least 6 months ago and suddenly, this error started to appear, the choice_label property solved the issue on the production server, although the entity had the magic toString method. – Carlos Delgado Oct 03 '19 at 16:55
9

I got the same error but i tweaked it a little bit by adding:

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

I'm sure i was getting null instead of a string value. (I was working with sonata-project).

Tomsgu
  • 1,016
  • 1
  • 11
  • 31
Abdenour Keddar
  • 121
  • 1
  • 6
  • Thanks, I got a similar error with EasyAdmin and it required `toString` to generate select input into forms. – Pete_Gore Jan 22 '19 at 08:05
1

so I solved the problem by get the value of relative parent in the method $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()
        );
    }

thanks!

Jazi
  • 6,569
  • 13
  • 60
  • 92
Falar
  • 519
  • 2
  • 5
  • 10
  • How did you come up with this? I've got a similar problem with a controller and nested one to many relations, and it's broken when there are some rows in the table (works fine when the db is empty). So I'm guessing that my problem is similar to yours (it is fixed by creating `__toString` but that feels like a hack to me). Knowing how you got that solution would help me solve my problem! – Benoit Duffez Jun 04 '17 at 12:45
0

You can also use the property accessor into your form:

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

            ))

And add 'property' => 'name' in your CategoriesDescriptionType.

By the way the @CoachNono answer is ok too.

Smashou
  • 378
  • 1
  • 12