Symfony 2 Embedded forms using one to many db relationship - forms

I'm have a problem embedding forms from different entities in one form, my form is being displayed with firstname [input] lastname [input] address - but the address has no input next to it.
Basically I want to create a form where the user can add first name, last name, address1, address2, city, country ect and submit it it as one, although it's different tables.
The main form is no problem the only issue I'm having is with the second embedded form. Any help would be greatly appreciated.
Here is my code:
Member class:
namespace Pomc\MembersBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Pomc\MembersBundle\Entity\Member
*/
class Member
{
/**
* #var integer $id
*/
private $id;
/**
* #var string $firstName
*/
private $firstName;
/**
* #var string $lastName
*/
private $lastName;
/**
* #var Pomc\MembersBundle\Entity\Address
*/
private $address;
/**
* #var Pomc\MembersBundle\Entity\Telephone
*/
private $telephone;
public function __construct()
{
$this->address = new \Doctrine\Common\Collections\ArrayCollection();
$this->telephone = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set firstName
*
* #param string $firstName
*/
public function setFirstName($firstName)
{
$this->firstName = $firstName;
}
/**
* Get firstName
*
* #return string
*/
public function getFirstName()
{
return $this->firstName;
}
/**
* Set lastName
*
* #param string $lastName
*/
public function setLastName($lastName)
{
$this->lastName = $lastName;
}
/**
* Get lastName
*
* #return string
*/
public function getLastName()
{
return $this->lastName;
}
/**
* Add address
*
* #param Pomc\MembersBundle\Entity\Address $address
*/
public function addAddress(\Pomc\MembersBundle\Entity\Address $address)
{
$this->address[] = $address;
}
/**
* Get address
*
* #return Doctrine\Common\Collections\Collection
*/
public function getAddress()
{
return $this->address;
}
/**
* Add telephone
*
* #param Pomc\MembersBundle\Entity\Telephone $telephone
*/
public function addTelephone(\Pomc\MembersBundle\Entity\Telephone $telephone)
{
$this->telephone[] = $telephone;
}
/**
* Get telephone
*
* #return Doctrine\Common\Collections\Collection
*/
public function getTelephone()
{
return $this->telephone;
}
}
Here is the address class:
namespace Pomc\MembersBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Pomc\MembersBundle\Entity\Address
*/
class Address
{
/**
* #var integer $id
*/
private $id;
/**
* #var string $addressType
*/
private $addressType;
/**
* #var string $firstLine
*/
private $firstLine;
/**
* #var string $secondLine
*/
private $secondLine;
/**
* #var string $city
*/
private $city;
/**
* #var string $postCode
*/
private $postCode;
/**
* #var string $country
*/
private $country;
/**
* #var Pomc\MembersBundle\Entity\Member
*/
private $member;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set addressType
*
* #param string $addressType
*/
public function setAddressType($addressType)
{
$this->addressType = $addressType;
}
/**
* Get addressType
*
* #return string
*/
public function getAddressType()
{
return $this->addressType;
}
/**
* Set firstLine
*
* #param string $firstLine
*/
public function setFirstLine($firstLine)
{
$this->firstLine = $firstLine;
}
/**
* Get firstLine
*
* #return string
*/
public function getFirstLine()
{
return $this->firstLine;
}
/**
* Set secondLine
*
* #param string $secondLine
*/
public function setSecondLine($secondLine)
{
$this->secondLine = $secondLine;
}
/**
* Get secondLine
*
* #return string
*/
public function getSecondLine()
{
return $this->secondLine;
}
/**
* Set city
*
* #param string $city
*/
public function setCity($city)
{
$this->city = $city;
}
/**
* Get city
*
* #return string
*/
public function getCity()
{
return $this->city;
}
/**
* Set postCode
*
* #param string $postCode
*/
public function setPostCode($postCode)
{
$this->postCode = $postCode;
}
/**
* Get postCode
*
* #return string
*/
public function getPostCode()
{
return $this->postCode;
}
/**
* Set country
*
* #param string $country
*/
public function setCountry($country)
{
$this->country = $country;
}
/**
* Get country
*
* #return string
*/
public function getCountry()
{
return $this->country;
}
/**
* Set member
*
* #param Pomc\MembersBundle\Entity\Member $member
*/
public function setMember(\Pomc\MembersBundle\Entity\Member $member)
{
$this->member = $member;
}
/**
* Get member
*
* #return Pomc\MembersBundle\Entity\Member
*/
public function getMember()
{
return $this->member;
}
}
Here is the memberform:
namespace Pomc\MembersBundle\Form\Type;
use \Symfony\Component\Form\AbstractType;
use \Symfony\Component\Form\FormBuilder;
class MemberType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('firstName');
$builder->add('lastName');
$builder->add('address','collection', array( 'type' => new AddressType(),
'allow_add' => true,
'prototype' => true,
'by_reference' => false,
));
}
public function getDefaultOptions(array $options)
{
return array('data_class' => 'Pomc\MembersBundle\Entity\Member');
}
/**
* Returns the name of this type.
*
* #return string The name of this type
*/
function getName()
{
return 'member';
}
}
Here is the address form:
namespace Pomc\MembersBundle\Form\Type;
use \Symfony\Component\Form\AbstractType;
use \Symfony\Component\Form\FormBuilder;
class AddressType extends AbstractType
{
public function buildForm(Formbuilder $builder, array $options)
{
$builder->add('firstLine');
}
public function getDefaultOptions(array $options)
{
return array('data_class' => 'Pomc\MembersBundle\Entity\Address');
}
/**
* Returns the name of this type.
*
* #return string The name of this type
*/
function getName()
{
return 'address';
}
function getIdentifier()
{
return 'address';
}
}
Here is the controller:
namespace Pomc\MembersBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use \Pomc\MembersBundle\Entity\Member;
use \Symfony\Component\HttpFoundation\Request;
use \Pomc\MembersBundle\Form\Type\MemberType;
class DefaultController extends Controller
{
public function indexAction($name)
{
return $this->render('PomcMembersBundle:Default:index.html.twig', array('name' => $name));
}
public function newAction(Request $request)
{
$member = new Member();
$form = $this->get('form.factory')->create(new MemberType());
if($request->getMethod() == 'POST')
{
$form->bindRequest($request);
if($form->isValid())
{
$em = $this->getDoctrine()->getEntityManager();
$em->persist($member);
$em->flush();
}
}
return $this->render('PomcMembersBundle:Default:new.html.twig', array( 'form'=> $form->createView(),));
}
}
Here is the template:
<form action="{{ path('member_new') }}" method="post" {{ form_enctype(form)}}>
{{ form_widget(form) }}
<div>
{{ form_row(form.address)}}
</div>
<input type="submit" />
</form>
Been a long time user of this site, but this is my first question.
Thank you

Oh I faced the same problem, but I found the solution, hope this will help you :-)
You're forgetting to add an Address object to the member entity.
In your action you'll need to do the following:
$member = new Member();
$member->addAddress(new Address());
$form = $this->createForm(new MemberType(), $member);
And then in your template:
{% for address in form.address %}
{{ form_widget(address.firstLine) }}
{% endfor %}
Btw your 'firstline' widget doesn't relate to an entity property.
Btw if you called addAddress two times, you would of course get two 'firstline' widgets in your form.
Hope this works. best of luck.

Llewellyn, do you mean something like thid:
public function editAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('imBundle:Inspecciones')->find($id);
$entity_valores = $em->getRepository('imBundle:ValoresInspecciones')->findByInspecciones($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Inspecciones entity.');
}
$entity->setValoresInspecciones($entity_valores);
$editForm = $this->createEditForm($entity);
$deleteForm = $this->createDeleteForm($id);
return $this->render('imBundle:Inspecciones:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}

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

Symfony 3.3 Form is returning NULL for one field

I'm trying to get INSERT values from a form into DB, one of my form fields is brand_id which is returning NULL upon submission.
There are two entities having Many to One relationship
Brand
id
name
Model
id
brand_id (FK)
name
image_url
comment
All fields return a value but the brand_id returns NULL
Code and Entitys are as follows:
brand Entity:
<?php
// src/coreBundle/Entity/Brand.php
namespace coreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use coreBundle\Entity\Model;
use Doctrine\Common\Collections\ArrayCollection;
/**
*#ORM\Entity
*#ORM\Table(name="brand")
*/
class brand
{
/**
* #var int
* #ORM\Id
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
public $id;
/**
*#ORM\Column(type="string", length=100)
*/
private $name;
/**
*#ORM\OneToMany(targetEntity="model", mappedBy="brands")
*/
protected $models;
public function __construct()
{
$this->models = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return brand
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Add model
*
* #param \coreBundle\Entity\model $model
*
* #return brand
*/
public function addModel(\coreBundle\Entity\model $model)
{
$this->models[] = $model;
return $this;
}
/**
* Remove model
*
* #param \coreBundle\Entity\model $model
*/
public function removeModel(\coreBundle\Entity\model $model)
{
$this->models->removeElement($model);
}
/**
* Get models
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getModels()
{
return $this->models;
}
}
model Entity :
<?php
// src/coreBundle/Entity/Model.php
namespace coreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use coreBundle\Entity\Brand;
/**
*#ORM\Entity
*#ORM\Table(name="model")
*/
class model
{
/**
* #var int
* #ORM\Id
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
public $id;
/**
*#ORM\Column(type="integer")
*/
public $brand_id;
/**
*#ORM\Column(type="string", length=100)
*/
private $name;
/**
*#ORM\Column(type="string", length=100)
*/
private $image_url;
/**
*#ORM\Column(type="string", length=200)
*/
private $comment;
/**
*#ORM\ManyToOne(targetEntity="brand", inversedBy="models")
*#ORM\JoinColumn(name="brand_id", referencedColumnName="id")
*/
protected $brands;
/**
* #ORM\OneToOne(targetEntity="model_item", mappedBy="models")
*/
private $model_items;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set brandId
*
* #param integer $brandId
*
* #return model
*/
public function setBrandId($brandId)
{
$this->brand_id = $brandId;
return $this;
}
/**
* Get brandId
*
* #return integer
*/
public function getBrandId()
{
return $this->brand_id;
}
/**
* Set name
*
* #param string $name
*
* #return model
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set imageUrl
*
* #param string $imageUrl
*
* #return model
*/
public function setImageUrl($imageUrl)
{
$this->image_url = $imageUrl;
return $this;
}
/**
* Get imageUrl
*
* #return string
*/
public function getImageUrl()
{
return $this->image_url;
}
/**
* Set comment
*
* #param string $comment
*
* #return model
*/
public function setComment($comment)
{
$this->comment = $comment;
return $this;
}
/**
* Get comment
*
* #return string
*/
public function getComment()
{
return $this->comment;
}
/**
* Set brands
*
* #param \coreBundle\Entity\brand $brands
*
* #return model
*/
public function setBrands(\coreBundle\Entity\brand $brands = null)
{
$this->brands = $brands;
return $this;
}
/**
* Get brands
*
* #return \coreBundle\Entity\brand
*/
public function getBrands()
{
return $this->brands;
}
}
My Controller Code:
public function newModelAction(Request $request)
{
$product = $this->getDoctrine()
->getRepository('coreBundle:brand')
->findAll();
if (!$product) {
throw $this->createNotFoundException(
'No product found for id '.$productId
);
}
$model = new model();
$form = $this->createFormBuilder($model)
->add('brand_id',TextType::class,array('label'=>'Brand Id'))
->add('name',TextType::class,array('label'=>'Model Name'))
->add('comment',TextType::class,array('label'=>'Comments'))
->add('image_url',TextType::class,array('label'=>'Image URL'))
->add('save',SubmitType::class, array('label'=>'Add Model'))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($model);
$em->flush();
return $this->render('coreBundle:layouts:newItem.html.twig',
array('form'=>$form->createView(),));
}
// ... do something, like pass the $product object into a template
return $this->render('coreBundle:layouts:newModel.html.twig',
array('form'=>$form->createView(),));
}
Try to remove this:
*#ORM\Column(type="integer")
*/
public $brand_id;
Because you have already the field for brands in this point:
/**
*#ORM\ManyToOne(targetEntity="brand", inversedBy="models")
*#ORM\JoinColumn(name="brand_id", referencedColumnName="id")
*/
protected $brands;
You need also to remove getter and seeter of brandId and remove brand_id from the form and adding this for example:
->add('brand', EntityType::class, array(
// query choices from this entity
'class' => 'AppBundle:Brand',
))
Try this
/**
*#ORM\ManyToOne(targetEntity="brand")
*#ORM\JoinColumn(nullable=false)
*/
protected $brands;

Display an image in a form type of some model SYLIUS

i have created a new model which have an attribute "image" , i have generated the CRUD using the SyliusResourcesBundle ,
what i'm trying to achieve is to display an image in the edit form type , how can i do that ? thx in advance
my form type :
<?php
namespace AppBundle\Form\Type;
use Sylius\Bundle\ResourceBundle\Form\Type\DefaultResourceType as BaseSliderType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class SliderType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder->add('lib','text'
);$builder->add('title','text'
);
$builder->add('description','text'
);
$builder->add('file',FileType::class
);
}
public function getName()
{
return 'app_slider';
}
}
?>
my model:
<?php
namespace AppBundle\Entity;
use Sylius\Component\Resource\Model\ResourceInterface;
use Doctrine\ORM\Mapping as ORM;
/**
* Slider
*/
class Slider implements ResourceInterface, \Serializable
{
/**
* #var int
*/
private $id;
/**
* #var string
*/
private $lib;
/**
* #var string
*/
private $title;
/**
* #var string
*/
private $description;
private $file;
/**
* #return mixed
*/
public function getFile()
{
return $this->file;
}
/**
* #param mixed $file
*/
public function setFile($file)
{
$this->file = $file;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set lib
*
* #param string $lib
* #return Slider
*/
public function setLib($lib)
{
$this->lib = $lib;
return $this;
}
/**
* Get lib
*
* #return string
*/
public function getLib()
{
return $this->lib;
}
/**
* Set title
*
* #param string $title
* #return Slider
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set description
*
* #param string $description
* #return Slider
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* #var string
*/
private $condition;
/**
* Set condition
*
* #param string $condition
* #return Slider
*/
public function setCondition($condition)
{
$this->condition = $condition;
return $this;
}
/**
* Get condition
*
* #return string
*/
public function getCondition()
{
return $this->condition;
}
/** #see \Serializable::serialize() */
public function serialize()
{
return serialize(array(
$this->id,
$this->lib,
$this->title,
$this->description,
// see section on salt below
// $this->salt,
));
}
/** #see \Serializable::unserialize() */
public function unserialize($serialized)
{
list (
$this->id,
$this->lib,
$this->title,
$this->description,
// see section on salt below
// $this->salt
) = unserialize($serialized);
}
}

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...

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.