Cannot insert multiple values with entity form when multiple is true - forms

It throws an error when I submit the form with multiple=true: When is false everything works as expected and one value is inserted to the table.
Catchable Fatal Error: Argument 1 passed to AppBundle\Entity\CustomersProducts::setProducts() must be an instance of AppBundle\Entity\Products, instance of Doctrine\Common\Collections\ArrayCollection given, called in /var/www/html/app/vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php on line 556 and defined
Products.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\Products;
/**
* Products
*
* #ORM\Table(name="products")
* #ORM\Entity(repositoryClass="AppBundle\Repository\ProductsRepository")
*/
class Products
{
/**
* #ORM\OneToMany(targetEntity="CustomersProducts", mappedBy="products")
*/
private $products;
public function __toString() {
return $this->name;
}
public function addProducts(Products $request)
{
$this->products->add($request);
return $this;
}
public function removeProducts(Products $request)
{
$this->products->removeElement($request);
return $this;
}
public function __construct() {
$this->products= new ArrayCollection();
}
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Products
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
}
CustomersProducts.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\Customers;
use AppBundle\Entity\Products;
/**
* CustomersProducts
*
* #ORM\Table(name="customers_products")
* #ORM\Entity(repositoryClass="AppBundle\Repository\CustomersProductsRepository")
*/
class CustomersProducts
{
/**
* #ORM\ManyToOne(targetEntity="Customers", inversedBy="customers")
* #ORM\JoinColumn(name="customer_id", referencedColumnName="id")
*/
private $customers;
public function getCustomers()
{
return $this->customers;
}
public function setCustomers(Customers $customer) // Please add a Use statement on top of your document
{
$this->customers = $customer;
return $this;
}
/**
* #ORM\ManyToOne(targetEntity="Products", inversedBy="products")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id")
*/
private $products;
public function getProducts()
{
return $this->products;
}
public function setProducts(Products $products) // Please add a Use statement on top of your document
{
var_dump($products->getName()); die();
$this->products = $products;
return $this;
}
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="version", type="string", length=255)
*/
private $version;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set version
*
* #param string $version
* #return CustomersProducts
*/
public function setVersion($version)
{
$this->version = $version;
return $this;
}
/**
* Get version
*
* #return string
*/
public function getVersion()
{
return $this->version;
}
}
CustomersProductsType.php
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class CustomersProductsType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('version')
->add('customers', 'entity', array(
'class' => 'AppBundle:Customers',
'multiple' =>false,
'property' => 'name',
))
->add('products', 'entity', array(
'class' => 'AppBundle:Products',
'multiple' =>true,
'property' => 'name',
))
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\CustomersProducts'
));
}
}
UPDATE:
After the change I'made from the suggestion now I get the following error:
Found entity of type Doctrine\Common\Collections\ArrayCollection on association AppBundle\Entity\CustomersProducts#products, but expecting AppBundle\Entity\Product

You have to rename entity Products to Product, because class that representing one database row (an entity) should have singular name.
Grammatically incorrect method name addProducts:
public function addProducts(Products $request)
refactor it to:
public function addProduct(Product $product) {
if ($this->products->contains($product)) {
return;
}
$this->products->add($product);
}
The same with remove method:
public function removeProducts(Products $request)
refactor to:
public function removeProduct(Product $product) {
if (!$this->products->contains($product)) {
return;
}
$this->products->removeElement($product);
}
Changes to CustomersProducts
/**
* #ORM\ManyToOne(targetEntity="Product", inversedBy="products")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id")
*/
private $product;
public function getProduct()
{
return $this->product;
}
public function setProduct(Product $product)
{
$this->product = $product;
}
You can find similar example and explanation in the article

Related

How embed fields of an other entity in sonata form?

I have two entities Sport and Tarif (translated by price) linked by ManyToOne relation.
I would like to have just one admin form (in Sonata Admin Bundle) to create or delete a Sport with three fields :
libelle ( = name)
valeurDeBase ( = price value) which is a number attribute of Tarif entity
conditionDeReduction ( = condition to have a discount) which is a text attribute of Tarif entity
I'm searching a way to do that and I found the use of CollectionType (https://sonata-project.org/bundles/doctrine-orm-admin/master/doc/reference/form_field_definition.html) to embed the Tarif fields in SportAdmin form but that's not working as you can see below :
Here are the entities :
Sport.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Sport
*
* #ORM\Table(name="sport")
* #ORM\Entity(repositoryClass="AppBundle\Repository\SportRepository")
*/
class Sport
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="libelle", type="string", length=255, unique=true)
*/
private $libelle;
/**
* Un Sport est lié à 1 et 1 seul Tarif
* #ORM\ManyToOne(targetEntity="Tarif")
* #ORM\JoinColumn(nullable=false)
*/
private $tarif;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set libelle
*
* #param string $libelle
* #return Sport
*/
public function setLibelle($libelle)
{
$this->libelle = $libelle;
return $this;
}
/**
* Get libelle
*
* #return string
*/
public function getLibelle()
{
return $this->libelle;
}
/**
* Constructor
*/
public function __construct()
{
$this->licences = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add licence
*
* #param \AppBundle\Entity\Licence $licence
*
* #return Sport
*/
public function addLicence(\AppBundle\Entity\Licence $licence)
{
$this->licences[] = $licence;
return $this;
}
/**
* Remove licence
*
* #param \AppBundle\Entity\Licence $licence
*/
public function removeLicence(\AppBundle\Entity\Licence $licence)
{
$this->licences->removeElement($licence);
}
/**
* Get licences
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getLicences()
{
return $this->licences;
}
/**
* Set tarif
*
* #param \AppBundle\Entity\Tarif $tarif
*
* #return Sport
*/
public function setTarif(\AppBundle\Entity\Tarif $tarif)
{
$this->tarif = $tarif;
return $this;
}
/**
* Get tarif
*
* #return \AppBundle\Entity\Tarif
*/
public function getTarif()
{
return $this->tarif;
}
}
Tarif.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Tarif
*
* #ORM\Table(name="tarif")
* #ORM\Entity(repositoryClass="AppBundle\Repository\TarifRepository")
*/
class Tarif
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="valeurDeBase", type="decimal", precision=10, scale=2)
*/
private $valeurDeBase;
/**
* #var string
*
* #ORM\Column(name="conditionReduction", type="text", nullable=true)
*/
private $conditionReduction;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set valeurDeBase
*
* #param string $valeurDeBase
* #return Tarif
*/
public function setValeurDeBase($valeurDeBase)
{
$this->valeurDeBase = $valeurDeBase;
return $this;
}
/**
* Get valeurDeBase
*
* #return string
*/
public function getValeurDeBase()
{
return $this->valeurDeBase;
}
/**
* Set conditionReduction
*
* #param string $conditionReduction
* #return Tarif
*/
public function setConditionReduction($conditionReduction)
{
$this->conditionReduction = $conditionReduction;
return $this;
}
/**
* Get conditionReduction
*
* #return string
*/
public function getConditionReduction()
{
return $this->conditionReduction;
}
}
SportAdmin.php
<?php
// src/AppBundle/Admin/SportAdmin.php
namespace AppBundle\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\CoreBundle\Form\Type\CollectionType;
class SportAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('libelle', 'text');
$formMapper->add('tarif', CollectionType::class, array(
'by_reference' => false
),
array(
'edit' => 'inline',
'inline' => 'table',
'sortable' => 'position',
));
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper->add('libelle');
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper->addIdentifier('id');
$listMapper->add('libelle');
$listMapper->add('tarif.valeurDeBase');
$listMapper->add('tarif.conditionReduction');
}
public function toString($object)
{
return $object instanceof Sport
? $object->getTitle()
: 'Sport'; // shown in the breadcrumb on the create view
}
}
TarifAdmin.php
<?php
// src/AppBundle/Admin/TarifAdmin.php
namespace AppBundle\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
class TarifAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('valeurDeBase', 'number');
$formMapper->add('conditionReduction', 'text');
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
}
protected function configureListFields(ListMapper $listMapper)
{
}
public function toString($object)
{
return $object instanceof Tarif
? $object->getTitle()
: 'Tarif'; // shown in the breadcrumb on the create view
}
}
Thank you for your help.
Finally I have created an admin block for Tarif and embed it in SportAdmin with sonata_type_admin. It works perfectly.
Here the SportAdmin.php
<?php
// src/AppBundle/Admin/SportAdmin.php
namespace AppBundle\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\CoreBundle\Form\Type\CollectionType;
class SportAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('libelle', 'text');
$formMapper->add('tarif', 'sonata_type_admin', array(), array(
'admin_code' => 'admin.tarif'
));
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper->add('libelle');
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper->addIdentifier('id');
$listMapper->add('libelle');
$listMapper->add('tarif.valeurDeBase');
$listMapper->add('tarif.conditionReduction');
}
public function toString($object)
{
return $object instanceof Sport
? $object->getTitle()
: 'Sport'; // shown in the breadcrumb on the create view
}
}

How to populate one-to-many/many-to-one tables with symfony2 forms?

I'm new in Symfony and I'm stuck with populating one-to-many/many-to-one tables.
I managed to display the form but when I submit it I got the following error:
Found entity of type AppBundle\Entity\Products on association AppBundle\Entity\Customers#customers_products, but expecting AppBundle\Entity\CustomersProducts
Here is my code:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\CustomersProducts;
/**
* Customers
*
* #ORM\Table(name="customers")
* #ORM\Entity(repositoryClass="AppBundle\Repository\CustomersRepository")
*/
class Customers
{
/** #ORM\OneToMany(targetEntity="CustomersProducts", mappedBy="customers") */
protected $customers_products;
public function __construct()
{
$this->customers_products = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getCustomersProducts()
{
return $this->customers_products->toArray();
}
public function setCustomersProducts($customers_products)
{
if (count($customers_products) > 0) {
foreach ($customers_products as $i) {
$this->addCustomersProducts($i);
}
}
return $this;
}
public function addCustomersProducts( $customers_products)
{
$this->customers_products->add($customers_products);
}
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="ip", type="string", length=255)
*/
private $ip;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Customers
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set ip
*
* #param string $ip
* #return Customers
*/
public function setIp($ip)
{
$this->ip = $ip;
return $this;
}
/**
* Get ip
*
* #return string
*/
public function getIp()
{
return $this->ip;
}
}
Products.php:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Products
*
* #ORM\Table(name="products")
* #ORM\Entity(repositoryClass="AppBundle\Repository\ProductsRepository")
*/
class Products
{
/** #ORM\OneToMany(targetEntity="CustomersProducts", mappedBy="products") */
protected $customers_products;
public function __construct()
{
$this->customers_products = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Products
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
}
CustomersProducts.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* CustomersProducts
*
* #ORM\Table(name="customers_products")
* #ORM\Entity(repositoryClass="AppBundle\Repository\CustomersProductsRepository")
*/
class CustomersProducts
{
/**
*
* #ORM\ManyToOne(targetEntity="Customers", inversedBy="customers_products")
* #ORM\JoinColumn(name="customer_id", referencedColumnName="id", nullable=false)
*/
protected $customers;
/**
*
* #ORM\ManyToOne(targetEntity="Products", inversedBy="customers_products")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id", nullable=false)
*/
protected $products;
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="version", type="string", length=255)
*/
private $version;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set version
*
* #param string $version
* #return CustomersProducts
*/
public function setVersion($version)
{
$this->version = $version;
return $this;
}
/**
* Get version
*
* #return string
*/
public function getVersion()
{
return $this->version;
}
}
CustomersType.php
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class CustomersType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('ip')
->add('customers_products', 'entity', array(
'class' => 'AppBundle:Products',
'multiple' =>true,
'expanded' => true,
'property' => 'name'
));
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Customers'
));
}
}

How to show a collection form with the exact number of records available in a table

I am using symfony2 and doctrine.
I have a list of contacts and they are classified in a number of groups.
These groups are stored in a table.
Then I have users in my application and for each users I want to specify their rights: no/read/write.
In order to achieve this I have created a userspermission table as such :
<?php
namespace Curuba\contactsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use APY\DataGridBundle\Grid\Mapping as GRID;
/**
* userspermissions
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Curuba\contactsBundle\Entity\userspermissionsRepository")
*/
class userspermissions
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="permission", type="string", length=10)
*
* #GRID\Column(title="Permission")
*
*/
private $permission;
/**
* #ORM\ManyToOne(targetEntity="groupes", inversedBy="permissions")
* #ORM\JoinColumn(nullable=false)
*
* #GRID\Column(title="Groupes")
*/
private $groupe;
/**
* #ORM\ManyToOne(targetEntity="users", inversedBy="permissions")
* #ORM\JoinColumn(nullable=false)
*
* #GRID\Column(title="Permission")
*/
private $user;
Now in my user form, I would need to show a table with all available groups and a drop-down list in front of them.
But I dont know how to achieve that without a collection and then asking the user to add a group permission, select a group and the according permission.
Thanks in advance.
You can use an ManyToOne relation.
For example with an User and Group
<?php
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="groups")
*/
class Group
{
const CLASS_NAME = __CLASS__;
/**
* #var integer
*
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(name="id",type="integer")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="label",type="string",length=255)
*/
private $label;
/**
* #param int $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #param string $label
*/
public function setLabel($label)
{
$this->label = $label;
}
/**
* #return string
*/
public function getLabel()
{
return $this->label;
}
/**
* #return string
*/
public function __toString()
{
return $this->getLabel();
}
}
and the User entity
<?php
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
*
* #ORM\Entity
* #ORM\Table(name="user")
*/
class User
{
const CLASS_NAME = __CLASS__;
/**
* #var integer
*
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(name="id",type="integer")
*/
private $id;
/**
* #var string
*
* #ORM\Column(type="string", name="label", length=255)
*/
private $label;
/**
* #ORM\ManyToMany(targetEntity="Group")
* #ORM\JoinTable(name="user_group",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="group_id", referencedColumnName="id")}
* )
**/
private $groups;
public function __construct()
{
$this->groups = new ArrayCollection();
}
/**
* #param int $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #param string $label
*/
public function setLabel($label)
{
$this->label = $label;
}
/**
* #return string
*/
public function getLabel()
{
return $this->label;
}
/**
* #param Group $group
*
* #return bool
*/
public function hasGroup(Group $group)
{
return $this->groups->contains($group);
}
/**
* #param Group $group
*
* #return $this
*/
public function addGroup(Group $group)
{
if (false === $this->hasGroup($group)) {
$this->groups->add($group);
}
return $this;
}
/**
* #return \Doctrine\Common\Collections\ArrayCollection
*/
public function getGroups()
{
return $this->groups;
}
/**
* #return string
*/
public function __toString()
{
return $this->getLabel();
}
}
and finally create an form type like this :
class UserType extends AbstractType
{
const NAME = 'userType';
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('label', 'text');
$builder->add('groups', 'entity', array(
'class' => Group::CLASS_NAME,
'multiple' => true,
'expanded' => true,
));
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => User::CLASS_NAME,
));
}
/**
* Returns the name of this type.
*
* #return string The name of this type
*/
public function getName()
{
return self::NAME;
}
}
I have found how to do this. This is in fact very simple and I was probably expecting something more complex...
I have added a function in my controller (could be in my entity...) and I cal this function when I create a new user entity or when I edit one (in case a groupe has been added in the mean time.
Here is the code:
private function autocompleteForm(users $user) {
$em = $this->getDoctrine()->getManager();
$groupes = $em->getRepository('contactsBundle:groupes')->findAll();
if ($user) {
foreach ($groupes as $groupe) {
$permission = $em->getRepository('contactsBundle:userspermissions')->findOneBy(array('groupe' => $groupe, 'user' => $user));
if(!$permission) {
$permission = new userspermissions();
$permission->setGroupe($groupe);
$user->addPermission($permission);
}
}
}
return $user;
}
I am happy to explain more if someone needs...

embedded to form symfony2

i work with symfony2 and when i embedded two form (person in group) have under problem:
Neither the property "PersonEntity" nor one of the methods "getPersonEntity()", "isPersonEntity()", "hasPersonEntity()", "_get()" or "_call()" exist and have public access in class "S118\ebrahimiBundle\Entity\GroupEntity".
my PersonEntity:
<?php
namespace S118\ebrahimiBundle\Entity;
use Doctrine\ORM\Mapping AS ORM;
/**
* #ORM\Entity
*/
class PersonEntity
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=100, nullable=false)
*/
private $f_name;
/**
* #ORM\Column(type="string", length=100, nullable=false)
*/
private $l_name;
/**
* #ORM\Column(type="string", length=100, nullable=true)
*/
private $tell;
/**
* #ORM\Column(type="string", length=100, nullable=true)
*/
private $fileName;
/**
* #ORM\OneToMany(targetEntity="S118\ebrahimiBundle\Entity\BuyEntity", mappedBy="PersonEntity")
*/
private $BuyEntities;
/**
* #ORM\OneToMany(targetEntity="S118\ebrahimiBundle\Entity\UsageEntity", mappedBy="PersonEntity")
*/
private $UsageEntities;
/**
* #ORM\ManyToOne(targetEntity="S118\ebrahimiBundle\Entity\GroupEntity", inversedBy="PersonEntities")
* #ORM\JoinColumn(name="Gid", referencedColumnName="id", nullable=false)
*/
private $GroupEntity;
/**
* Constructor
*/
public function __construct()
{
$this->BuyEntities = new \Doctrine\Common\Collections\ArrayCollection();
$this->UsageEntities = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set f_name
*
* #param string $fName
* #return PersonEntity
*/
public function setFName($fName)
{
$this->f_name = $fName;
return $this;
}
/**
* Get f_name
*
* #return string
*/
public function getFName()
{
return $this->f_name;
}
/**
* Set l_name
*
* #param string $lName
* #return PersonEntity
*/
public function setLName($lName)
{
$this->l_name = $lName;
return $this;
}
/**
* Get l_name
*
* #return string
*/
public function getLName()
{
return $this->l_name;
}
/**
* Set tell
*
* #param string $tell
* #return PersonEntity
*/
public function setTell($tell)
{
$this->tell = $tell;
return $this;
}
/**
* Get tell
*
* #return string
*/
public function getTell()
{
return $this->tell;
}
/**
* Set fileName
*
* #param string $fileName
* #return PersonEntity
*/
public function setFileName($fileName)
{
$this->fileName = $fileName;
return $this;
}
/**
* Get fileName
*
* #return string
*/
public function getFileName()
{
return $this->fileName;
}
/**
* Add BuyEntities
*
* #param \S118\ebrahimiBundle\Entity\BuyEntity $buyEntities
* #return PersonEntity
*/
public function addBuyEntitie(\S118\ebrahimiBundle\Entity\BuyEntity $buyEntities)
{
$this->BuyEntities[] = $buyEntities;
return $this;
}
/**
* Remove BuyEntities
*
* #param \S118\ebrahimiBundle\Entity\BuyEntity $buyEntities
*/
public function removeBuyEntitie(\S118\ebrahimiBundle\Entity\BuyEntity $buyEntities)
{
$this->BuyEntities->removeElement($buyEntities);
}
/**
* Get BuyEntities
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getBuyEntities()
{
return $this->BuyEntities;
}
/**
* Add UsageEntities
*
* #param \S118\ebrahimiBundle\Entity\UsageEntity $usageEntities
* #return PersonEntity
*/
public function addUsageEntitie(\S118\ebrahimiBundle\Entity\UsageEntity $usageEntities)
{
$this->UsageEntities[] = $usageEntities;
return $this;
}
/**
* Remove UsageEntities
*
* #param \S118\ebrahimiBundle\Entity\UsageEntity $usageEntities
*/
public function removeUsageEntitie(\S118\ebrahimiBundle\Entity\UsageEntity $usageEntities)
{
$this->UsageEntities->removeElement($usageEntities);
}
/**
* Get UsageEntities
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUsageEntities()
{
return $this->UsageEntities;
}
/**
* Set GroupEntity
*
* #param \S118\ebrahimiBundle\Entity\GroupEntity $groupEntity
* #return PersonEntity
*/
public function setGroupEntity(\S118\ebrahimiBundle\Entity\GroupEntity $groupEntity)
{
$this->GroupEntity = $groupEntity;
return $this;
}
/**
* Get GroupEntity
*
* #return \S118\ebrahimiBundle\Entity\GroupEntity
*/
public function getGroupEntity()
{
return $this->GroupEntity;
}
public function __toString()
{
return $this->f_name.' '.$this->l_name;
}
}
and my group entity:
<?php
namespace S118\ebrahimiBundle\Entity;
use Doctrine\ORM\Mapping AS ORM;
/**
* #ORM\Entity
*/
class GroupEntity
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $name;
/**
* #ORM\OneToMany(targetEntity="S118\ebrahimiBundle\Entity\BuyEntity", mappedBy="GroupEntity")
*/
private $BuyEntities;
/**
* #ORM\OneToMany(targetEntity="S118\ebrahimiBundle\Entity\PersonEntity", mappedBy="GroupEntity")
*/
private $PersonEntities;
/**
* Constructor
*/
public function __construct()
{
$this->BuyEntities = new \Doctrine\Common\Collections\ArrayCollection();
$this->PersonEntities = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return GroupEntity
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Add BuyEntities
*
* #param \S118\ebrahimiBundle\Entity\BuyEntity $buyEntities
* #return GroupEntity
*/
public function addBuyEntitie(\S118\ebrahimiBundle\Entity\BuyEntity $buyEntities)
{
$this->BuyEntities[] = $buyEntities;
return $this;
}
/**
* Remove BuyEntities
*
* #param \S118\ebrahimiBundle\Entity\BuyEntity $buyEntities
*/
public function removeBuyEntitie(\S118\ebrahimiBundle\Entity\BuyEntity $buyEntities)
{
$this->BuyEntities->removeElement($buyEntities);
}
/**
* Get BuyEntities
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getBuyEntities()
{
return $this->BuyEntities;
}
/**
* Add PersonEntities
*
* #param \S118\ebrahimiBundle\Entity\PersonEntity $personEntities
* #return GroupEntity
*/
public function addPersonEntitie(\S118\ebrahimiBundle\Entity\PersonEntity $personEntities)
{
$this->PersonEntities[] = $personEntities;
return $this;
}
/**
* Remove PersonEntities
*
* #param \S118\ebrahimiBundle\Entity\PersonEntity $personEntities
*/
public function removePersonEntitie(\S118\ebrahimiBundle\Entity\PersonEntity $personEntities)
{
$this->PersonEntities->removeElement($personEntities);
}
/**
* Get PersonEntities
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getPersonEntities()
{
return $this->PersonEntities;
}
public function __toString()
{
return $this->name;
}
}
and my group view :
{% extends '::base.html.twig' %}
{% block body -%}
<h1>GroupEntity creation</h1>
{{ form(form) }}
<ul class="record_actions">
<li>
<a href="{{ path('group') }}">
Back to the list
</a>
</li>
</ul>
{% endblock %}
and my person form:
<?php
namespace S118\ebrahimiBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class PersonEntityType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('f_name')
->add('l_name')
->add('tell')
->add('fileName')
->add('GroupEntity')
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'S118\ebrahimiBundle\Entity\PersonEntity'
));
}
/**
* #return string
*/
public function getName()
{
return 's118_ebrahimibundle_personentity';
}
}
and my group form:
<?php
namespace S118\ebrahimiBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class GroupEntityType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('PersonEntity','collection', array('type' => new PersonEntityType()))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'S118\ebrahimiBundle\Entity\GroupEntity'
));
}
/**
* #return string
*/
public function getName()
{
return 's118_ebrahimibundle_groupentity';
}
}
why???
You GroupEntityType form type is looking for a 'PersonEntity' field in your GroupEntity entity. You have a oneToMany PersonEntities instead.
Try to replace PersonEntity to PersonEntities in your GroupEntityType.

Doctrine Mongo document + Embed a Collection of Forms

Project with symfony 2 and mongoDB.
I'm following this tutorial: http://symfony.com/doc/current/cookbook/form/form_collections.html
But once I save the form I get this error:
Cannot create a DBRef, the document is not an object
Line of crash:
https://github.com/doctrine/mongodb-odm/blob/master/lib/Doctrine/ODM/MongoDB/DocumentManager.php#L691
Form code:
namespace Fonts\FontsBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class FamilyType extends AbstractType
{
public function __construct($dm)
{
$this->dm = $dm;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', 'text', array('max_length' => 50, 'error_bubbling' => true));
$builder->add('fonts', 'collection', array(
'type' => new FontType($this->dm),
'allow_add' => true,
'by_reference' => false,
));
}
public function getName()
{
return 'Family';
}
}
Controller code:
namespace Fonts\FontsBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Fonts\FontsBundle\Document\Family;
use Fonts\FontsBundle\Document\Font;
use Fonts\FontsBundle\Form\Type\FamilyType;
class FamilyBackendController extends BaseController
{
public function newAction()
{
try {
$family = new Family();
$form = $this->createForm(new FamilyType($this->getMongoService()), $family);
$request = $this->getRequest();
if ($request->getMethod() == 'POST')
{
$form->bind($request);
if ($form->isValid())
{
$this->persist($family);
$this->get('session')->setFlash('notice', 'Item successfully created.');
return ($request->request->get('save') === 'Save') ?
new RedirectResponse($this->generateUrl('backend_familys_list')) :
new RedirectResponse($this->generateUrl('backend_familys_new'));
}
}
return $this->render('FontsBundle:Backend:newFamily.html.twig', array(
'form' => $form->createView(),
));
} catch(\Exception $e) {
return new Response($e->getMessage());
}
}
}
Document:
<?php
namespace Fonts\FontsBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Fonts\FontsBundle\Service\SlugService;
/**
* #MongoDB\Document(repositoryClass="Fonts\FontsBundle\Repository\FamilyRepository")
*/
class Family
{
/**
* #MongoDB\Id
*/
protected $id;
/**
* #MongoDB\String
* #MongoDB\UniqueIndex(safe=true)
* #Assert\NotBlank(message="FamilyName value should not be blank.")
* #Assert\MinLength(limit=3,message="FamilyName must have at least {{ limit }} characters.")
* #Assert\MaxLength(limit=50,message="FamilyName must have maximum {{ limit }} characters.")
*/
protected $name;
/**
* #MongoDB\ReferenceMany(targetDocument="Font", simple=true)
* #Assert\NotBlank(message="Fonts should not be blank.")
*/
protected $fonts;
/**
* #MongoDB\String
* #MongoDB\UniqueIndex(safe=true)
*/
protected $slug;
/**
* #MongoDB\Int
*/
protected $createdAt;
public function __construct()
{
$this->fonts = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return id $id
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Family
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string $name
*/
public function getName()
{
return $this->name;
}
/**
* Add fonts
*
* #param Fonts\FontsBundle\Document\Font $fonts
*/
public function addFonts(\Fonts\FontsBundle\Document\Font $fonts)
{
$this->fonts[] = $fonts;
}
/**
* Set fonts
*
* #param Doctrine\Common\Collections\Collection $fonts
*/
public function setFonts($fonts)
{
$this->fonts = $fonts;
}
/**
* Get fonts
*
* #return Doctrine\Common\Collections\Collection $fonts
*/
public function getFonts()
{
return $this->fonts;
}
/**
* Set slug
*
* #param string $slug
* #return Family
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* #return string $slug
*/
public function getSlug()
{
return $this->slug;
}
/**
* Set createdAt
*
* #param int $createdAt
* #return Family
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
/**
* Get createdAt
*
* #return int $createdAt
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* #MongoDB\PrePersist
*/
public function prePersist()
{
$this->setCreatedAt(time());
$slugService = new SlugService();
$this->setSlug($slugService->slug($this->getName()));
}
/**
* #MongoDB\PreUpdate
*/
public function preUpdate()
{
$slugService = new SlugService();
$this->setSlug($slugService->slug($this->getName()));
}
}
The form crash when I try to persist the object in the controller action_
$this->persist($family);
I tried lot of options but no one with good results. If you have some idea, please reply.