Symfony - Integrity constraint violation: 1062 Duplicate entry - php

I tried to find an answer for my question but it was unsuccessful. I'm using Symfony (Ive been using it 2 months) and I have a problem when I want to make many to many relationship.
I have homes and I have services. One home can have a lot of services and one service can have a lot of homes. Everything is ok and I understand the way many to many works with the doctrine, i persisted all values before flush in my controller, but i always get this message:
An exception occurred while executing 'INSERT INTO homess_services (home_id, service_id) VALUES (?, ?)' with params [25, 7]:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '25' for key 'home_id'
My codes are (home entity):
<?php
namespace Filip\SymfonyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Filip\SymfonyBundle\FilipSymfonyBundle;
/**
* Home
*
* #ORM\Table(name="homes")
* #ORM\Entity
*
*
*/
class Home
{
/**
* #var ArrayCollection
*
* #ORM\ManyToMany(targetEntity="Service", inversedBy="homes")
* #ORM\JoinTable(name="homess_services")
*/
protected $services;
public function __construct() {
$this->photos = new ArrayCollection();
$this->services = new ArrayCollection();
}
/**
* Renders a publication as a string
*
* #return string
*/
public function __toString (){
return $this->getName();
}
/**
* Add services
*
* #param \Filip\SymfonyBundle\Entity\Service $services
* #return Home
*/
public function addService(\Filip\SymfonyBundle\Entity\Service $services)
{
$this->services[] = $services;
return $this;
}
/**
* Remove services
*
* #param \Filip\SymfonyBundle\Entity\Service $services
*/
public function removeService(\Filip\SymfonyBundle\Entity\Service $services)
{
$this->services->removeElement($services);
}
/**
* Get services
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getServices()
{
return $this->services;
}
Service entity:
<?php
namespace Filip\SymfonyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Filip\SymfonyBundle\FilipSymfonyBundle;
/**
* Service
*
* #ORM\Table("services")
* #ORM\Entity
*/
class Service
{
/**
* #var ArrayCollection
*
* #ORM\ManyToMany(targetEntity="Home", mappedBy="services")
*/
protected $homes;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM
\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="category", type="string", length=45)
*/
private $category;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=45)
*/
private $name;
/**
* Renders a service as a string
*
* #return string
*/
/**
* Get id
*
6
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set category
*
* #param string $category
* #return Service
*/
public function setCategory($category)
{
$this->category = $category;
return $this;
}
/**
* Get category
*
* #return string
*/
public function getCategory()
{
return $this->category;
}
/**
* Set name
*
* #param string $name
* #return Service
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
public function __construct()
{
$this->homes = new ArrayCollection();
}
/**
* Add homes
*
* #param \Filip\SymfonyBundle\Entity\Home $homes
* #return Service
*/
public function addHome(\Filip\SymfonyBundle\Entity\Home $homes)
{
$this->homes[] = $homes;
return $this;
}
/**
* Remove homes
*
* #param \Filip\SymfonyBundle\Entity\Home $homes
*/
public function removeHome(\Filip\SymfonyBundle\Entity\Home $homes)
{
$this->homes->removeElement($homes);
}
/**
* Get homes
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getHomes()
{
return $this->homes;
}
}
Form(HomeType):
<?php
namespace Filip\SymfonyBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class HomeType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('city')
->add('region')
->add('phone')
->add('address')
->add('email')
->add('website')
->add('content')
->add('youtubeApi')
->add('premium')
->add('services' , 'entity' , array(
'class' => 'FilipSymfonyBundle:Service' ,
'property' => 'name' ,
'expanded' => true ,
'multiple' => true ,
));
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Filip\SymfonyBundle\Entity\Home'
));
}
/**
* #return string
*/
public function getName()
{
return 'filip_symfonybundle_home';
}
}
Home controller:
/**
* Creates a new Home entity.
*
* #Route("/", name="home_create")
* #Method("POST")
* #Template("FilipSymfonyBundle:Home:new.html.twig")
*/
public function createAction(Request $request)
{
$entity = new Home();
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$services = $entity->getServices();
foreach($services as $service) {
$entity->addService($service);
$em->persist($service);
}
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('home_show', array('id' => $entity->getId())));
}
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
/**
* Creates a form to create a Home entity.
*
* #param Home $entity The entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(Home $entity)
{
$form = $this->createForm(new HomeType(), $entity, array(
'action' => $this->generateUrl('home_create'),
'method' => 'POST',
));
$form->add('submit', 'submit', array('label' => 'Create'));
return $form;
}

in the if($form->isValid()) part you don't need to call the addService() method in the foreach loop as Symfony will do this for you on the handleRequest() call.
If the Home entity is at the owning side of the ManyToMany relation you don't need to persist every Service object too. So you can try to remove the whole foreach loop too.

Related

Neither the property "parent" build form Symfony 2 Self-Referenced mapping

I have an Entity containing Self-Referenced mapping. I would like to add new categories and subcategories to the systems but I do not know how to build the add form correctly. Gets are generated and setters are generated in Entity. I'm getting an error:
Neither the property "parent" nor one of the methods
"addParent()"/"removeParent()", "setParent()", "parent()", "__set()"
or "__call()" exist and have public access in class
"Adevo\ClassifiedsBundle\Entity\ClassifiedsCategory".
namespace XXX\ClassifiedsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="XXX\ClassifiedsBundle\Repository\ClassifiedsCategoryRepository")
* #ORM\Table(name="classifieds_categories")
*/
class ClassifiedsCategory extends ClassifiedsAbstractTaxonomy {
/**
* #ORM\OneToMany(
* targetEntity = "Classifieds",
* mappedBy = "category"
* )
*/
protected $classifieds;
/**
* #ORM\ManyToMany(targetEntity="ClassifiedsCategory", mappedBy="parent")
*/
private $children;
/**
*
* #ORM\ManyToMany(targetEntity="ClassifiedsCategory", inversedBy="children")
* #ORM\JoinTable(name="subCategory",
* joinColumns={#ORM\JoinColumn(name="category_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="parent_id", referencedColumnName="id")}
* )
*/
private $parent;
/**
* Constructor
*/
public function __construct() {
$this->children = new \Doctrine\Common\Collections\ArrayCollection();
$this->parent = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add classified
*
* #param \XXX\ClassifiedsBundle\Entity\Classifieds $classified
*
* #return ClassifiedsCategory
*/
public function addClassified(\XXX\ClassifiedsBundle\Entity\Classifieds $classified) {
$this->classifieds[] = $classified;
return $this;
}
/**
* Remove classified
*
* #param \XXX\ClassifiedsBundle\Entity\Classifieds $classified
*/
public function removeClassified(\XXX\ClassifiedsBundle\Entity\Classifieds $classified) {
$this->classifieds->removeElement($classified);
}
/**
* Get classifieds
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getClassifieds() {
return $this->classifieds;
}
/**
* Add child
*
* #param \XXX\ClassifiedsBundle\Entity\ClassifiedsCategory $child
*
* #return ClassifiedsCategory
*/
public function addChild(\XXX\ClassifiedsBundle\Entity\ClassifiedsCategory $child) {
$this->children[] = $child;
return $this;
}
/**
* Remove child
*
* #param \XXX\ClassifiedsBundle\Entity\ClassifiedsCategory $child
*/
public function removeChild(\XXX\ClassifiedsBundle\Entity\ClassifiedsCategory $child) {
$this->children->removeElement($child);
}
/**
* Get children
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getChildren() {
return $this->children;
}
/**
* Add parent
*
* #param \XXX\ClassifiedsBundle\Entity\ClassifiedsCategory $parent
*
* #return ClassifiedsCategory
*/
public function addParent(\XXX\ClassifiedsBundle\Entity\ClassifiedsCategory $parent) {
$this->parent[] = $parent;
return $this;
}
/**
* Remove parent
*
* #param \XXX\ClassifiedsBundle\Entity\ClassifiedsCategory $parent
*/
public function removeParent(\XXX\ClassifiedsBundle\Entity\ClassifiedsCategory $parent) {
$this->parent->removeElement($parent);
}
/**
* Get parent
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getParent() {
return $this->parent;
}
}
<pre>
namespace XXX\ClassifiedsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\MappedSuperclass
* #ORM\HasLifecycleCallbacks
*/
abstract class ClassifiedsAbstractTaxonomy {
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=120, unique=true)
*/
private $name;
/**
* #ORM\Column(type="string", length=120, unique=true)
*/
private $slug;
protected $classifieds;
/**
* Constructor
*/
public function __construct()
{
$this->classifieds = new \Doctrine\Common\Collections\ArrayCollection();
// $this->children = new \Doctrine\Common\Collections\ArrayCollection();
// $this->parent = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add classifieds
*
* #param \XXX\ClassifiedsBundle\Entity\Classifieds $classifieds
* #return ClassifiedsCategory
*/
public function addClassifieds(\XXX\ClassifiedsBundle\Entity\Classifieds $classifieds)
{
$this->classifieds[] = $classifieds;
return $this;
}
/**
* Remove classifieds
*
* #param \XXX\ClassifiedsBundle\Entity\Classifieds $classifieds
*/
public function removeClassifieds(\XXX\ClassifiedsBundle\Entity\Classifieds $classifieds)
{
$this->classifieds->removeElement($classifieds);
}
/**
* Get classifieds
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getCompanies()
{
return $this->classifieds;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return AbstractTaxonomy
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set slug
*
* #param string $slug
* #return AbstractTaxonomy
*/
public function setSlug($slug)
{
$this->slug = \XXX\ClassifiedsBundle\Libs\Utils::sluggify($slug);
return $this;
}
/**
* Get slug
*
* #return string
*/
public function getSlug()
{
return $this->slug;
}
/**
* #ORM\PrePersist
* #ORM\PreUpdate
*/
public function preSave(){
if(null === $this->slug){
$this->setSlug($this->getName());
}
}
}
namespace XXX\AdminBundle\Form\Type;
use XXX\AdminBundle\Form\Type\ClassifiedsTaxonomyType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ClassifiedsCategoryType extends ClassifiedsTaxonomyType {
public function getName() {
return 'taxonomy';
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('name', 'text', array(
'label' => 'Tytuł'
))
->add('slug', 'text', array(
'label' => 'Alias'
))
->add('parent', 'entity', array(
'class' => 'XXX\ClassifiedsBundle\Entity\ClassifiedsCategory',
'property' => 'name',
'empty_value' => 'Choose a parent category',
'required' => false,
))
->add('save', 'submit', array(
'label' => 'Zapisz'
));
}
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
'data_class' => 'XXX\ClassifiedsBundle\Entity\ClassifiedsCategory'
));
}
}
Your FormType ClassifiedsCategoryType is expecting an instance of ClassifiedsCategory and this need the attribute parent so far so good. But when you handle the request from your form to the controller, the formbuilder component tries to set the entered value to the attribute via the set method on the entity. This set method (setParent) is missing in your entity class.
So you have to implement it like this:
public function setParent($parent)
{
$this->parent = $parent;
return $this;
}

symfony2.3, persist related entity with foregin key

i'm looking for nice way to persist 2 objects to db via doctrine in symfony 2.3
class CatController extends Controller
{
/**
* Creates a new Cat entity.
*
*/
public function createAction(Request $request)
{
$entity = new Cat();
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity); <-- Split it or what ?
$em->flush();
return $this->redirect($this->generateUrl('cat_show', array('id' => $entity->getId())));
}
return $this->render('ViszmanCatBundle:Cat:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
when form is validated i can get post data and create 2 objects with that data but i think there should be clearer way to do this, above code is working not as i wanted, it only inserts foreign key to related entity when i do this:
class CatType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', 'text')
->add('meetings','collection',
array('type' => new MeetingType(),
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
)
);
}
class MeetingType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$plDays = array('Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota', 'Niedziela');
$builder
->add('meetingDay', 'choice', array('choices' => $plDays))
->add('meetingTime', 'time',)
->add('cat', 'entity', array('class' => 'ViszmanCatBundle:Cat', 'property' => 'name'))
;
}
entities: Cat
namespace Viszman\CatBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Cat
*
* #ORM\Table()
* #ORM\Entity
*/
class Congregation
{
/**
* #var integer
*
* #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;
/**
* #ORM\OneToMany(targetEntity="Viszman\CatBundle\Entity\Member", mappedBy="cat")
*/
private $members;
/**
* #ORM\OneToMany(targetEntity="Viszman\CatBundle\Entity\Meeting", mappedBy="cat", cascade={"persist"})
*/
private $meetings;
public function __construct(){
$this->members = new \Doctrine\Common\Collections\ArrayCollection();
$this->meetings = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Cat
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Add members
*
* #param \Viszman\CatBundle\Entity\Member $members
* #return Cat
*/
public function addMember(\Viszman\CatBundle\Entity\Member $members)
{
$this->members[] = $members;
return $this;
}
/**
* Remove members
*
* #param \Viszman\CatBundle\Entity\Member $members
*/
public function removeMember(\Viszman\CatBundle\Entity\Member $members)
{
$this->members->removeElement($members);
}
/**
* Get members
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getMembers()
{
return $this->members;
}
/**
* Add meetings
*
* #param \Viszman\CationBundle\Entity\Meeting $meetings
* #return Cat
*/
public function addMeeting(\Viszman\CatBundle\Entity\Meeting $meetings)
{
$this->meetings[] = $meetings;
return $this;
}
/**
* Remove meetings
*
* #param \Viszman\CatBundle\Entity\Meeting $meetings
*/
public function removeMeeting(\Viszman\CatBundle\Entity\Meeting $meetings)
{
$this->meetings->removeElement($meetings);
}
/**
* Get meetings
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getMeetings()
{
return $this->meetings;
}
namespace Viszman\CatBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Meeting
*
* #ORM\Table()
* #ORM\Entity
*/
class Meeting
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="meeting_day", type="smallint")
*/
private $meetingDay;
/**
* #var \DateTime
*
* #ORM\Column(name="meeting_time", type="time")
*/
private $meetingTime;
/**
* #ORM\ManyToOne(targetEntity="Viszman\CatBundle\Entity\Cat", inversedBy="meetings")
* #ORM\JoinColumn(name="cat_id", referencedColumnName="id")
*/
private $cat;
public function __construct()
{
$this->created = new \DateTime();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set meetingDay
*
* #param integer $meetingDay
* #return Meeting
*/
public function setMeetingDay($meetingDay)
{
$this->meetingDay = $meetingDay;
return $this;
}
/**
* Get meetingDay
*
* #return integer
*/
public function getMeetingDay()
{
return $this->meetingDay;
}
/**
* Set cat
*
* #param \Viszman\CatBundle\Entity\Cat $cat
* #return Member
*/
public function setCat(\Viszman\CatBundle\Entity\Cat $cat = null)
{
$this->cat = $cat;
return $this;
}
/**
* Get cat
*
* #return \stdClass
*/
public function getCat()
{
return $this->cat;
}
/**
* Set meetingTime
*
* #param \DateTime $meetingTime
* #return Meeting
*/
public function setMeetingTime($meetingTime)
{
$this->meetingTime = $meetingTime;
return $this;
}
/**
* Get meetingTime
*
* #return \DateTime
*/
public function getMeetingTime()
{
return $this->meetingTime;
}
this generate embedded form with unwanted data, meaning in Meeting section i need to choice Cat, but i dont want to, what i want is that meeting is on default attached to Cat on create, update. Do i need to change something in Cat or Meeting Entity? I don't know if i'm clear, sorry for my poor english
You need to remove this line in the MeetingType:
->add('cat', 'entity', array('class' => 'ViszmanCatBundle:Cat', 'property' => 'name'))
Then in yout Controller persist your Cat entity and yout Meeting entity (which you can find using cat's getMeetings method).
If you want both to be persisted in one shot, take a look at the cascade operation for Doctrine entities.

symfony2 Catchable Fatal Error: Object of class could not be converted to string

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?
You need to implement the __toString() method in your Apw\BlackbullBundle\Entity\CategoriesDescription.
You could do:
public function __toString() {
return $this->name;
}
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,
))
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).
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!
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.

Symfony2 Form Mapping Issue

Im having issues with data mapping to an entity after it is submitted
The Entity:
<?php
namespace Site\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\EntityManager;
use JMS\Serializer\Annotation as Serializer;
use JMS\Serializer\Annotation\Groups;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
/**
* UserAddress
*
* #ORM\Table(name="user_address")
* #ORM\Entity
*
* #Serializer\ExclusionPolicy("all")
* ---------- SERIALIZER GROUPS -----
* all -- All entries
*/
class UserAddress
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*
* #Serializer\Type("integer")
* #Serializer\Expose
* #serializer\SerializedName("ID")
* #serializer\Groups({"all"})
*/
public $ID;
/**
* #var integer
*
* #ORM\Column(name="user_id", type="integer", nullable=false)
*/
public $UserId;
/**
* #var integer
*
* #ORM\Column(name="level_id", type="integer", nullable=false)
*
* #Serializer\Type("integer")
* #Serializer\Expose
* #serializer\SerializedName("LevelId")
* #serializer\Groups({"all"})
*/
public $LevelId;
/**
* #var integer
*
* #ORM\Column(name="address_type_id", type="integer", nullable=false)
*
* #Serializer\Type("integer")
* #Serializer\Expose
* #serializer\SerializedName("AddressTypeId")
* #serializer\Groups({"all"})
*
* #Assert\NotBlank()
*/
public $AddressTypeId;
/**
* #var string
*
* #ORM\Column(name="address_data", type="text", nullable=false)
*
* #Serializer\Type("string")
* #Serializer\Expose
* #serializer\SerializedName("Address Data")
* #serializer\Groups({"all"})
*
* #Assert\NotBlank()
*/
public $AddressData;
/**
* #var integer
*
* #ORM\Column(name="public_yn", type="integer", nullable=false)
*
* #Serializer\Type("boolean")
* #Serializer\Expose
* #serializer\SerializedName("PublicYN")
* #serializer\Groups({"all"})
*
* #Assert\NotBlank()
*/
public $PublicYN;
/**
* #var integer
*
* #ORM\Column(name="primary_yn", type="integer", nullable=false)
*
* #Serializer\Type("boolean")
* #Serializer\Expose
* #serializer\SerializedName("PrimaryYN")
* #serializer\Groups({"all"})
*
* #Assert\NotBlank()
*/
public $PrimaryYN;
/**
* #ORM\ManyToOne(targetEntity="Site\UserBundle\Entity\UserMain", inversedBy="UserAddress")
* #ORM\JoinColumn(name="user_id", referencedColumnName="user_id")
*/
public $User;
/**
* #ORM\ManyToOne(targetEntity="Site\UserBundle\Entity\UserAddressType", inversedBy="UserAddress")
* #ORM\JoinColumn(name="address_type_id", referencedColumnName="address_type_id")
*
* #Serializer\Type("Site\UserBundle\Entity\UserAddressType")
* #Serializer\Expose
* #serializer\SerializedName("UserAddressType")
* #serializer\Groups({"all"})
*/
public $UserAddressType;
/**
* Get ID
*
* #return integer
*/
public function getID()
{
return $this->ID;
}
/**
* Set UserId
*
* #param integer $userId
* #return UserAddress
*/
public function setUserId($userId)
{
$this->UserId = $userId;
return $this;
}
/**
* Get UserId
*
* #return integer
*/
public function getUserId()
{
return $this->UserId;
}
/**
* Set LevelId
*
* #param integer $levelId
* #return UserAddress
*/
public function setLevelId($levelId)
{
$this->LevelId = $levelId;
return $this;
}
/**
* Get LevelId
*
* #return integer
*/
public function getLevelId()
{
return $this->LevelId;
}
/**
* Set AddressTypeId
*
* #param integer $addressTypeId
* #return UserAddress
*/
public function setAddressTypeId($addressTypeId)
{
$this->AddressTypeId = $addressTypeId;
return $this;
}
/**
* Get AddressTypeId
*
* #return integer
*/
public function getAddressTypeId()
{
return $this->AddressTypeId;
}
/**
* Set AddressData
*
* #param string $addressData
* #return UserAddress
*/
public function setAddressData($addressData)
{
$this->AddressData = $addressData;
return $this;
}
/**
* Get AddressData
*
* #return string
*/
public function getAddressData()
{
return $this->AddressData;
}
/**
* Set PublicYN
*
* #param integer $publicYN
* #return UserAddress
*/
public function setPublicYN($publicYN)
{
$this->PublicYN = $publicYN;
return $this;
}
/**
* Get PublicYN
*
* #return integer
*/
public function getPublicYN()
{
return $this->PublicYN;
}
/**
* Set PrimaryYN
*
* #param integer $primaryYN
* #return UserAddress
*/
public function setPrimaryYN($primaryYN)
{
$this->PrimaryYN = $primaryYN;
return $this;
}
/**
* Get PrimaryYN
*
* #return integer
*/
public function getPrimaryYN()
{
return $this->PrimaryYN;
}
/**
* Set User
*
* #param \Site\UserBundle\Entity\UserMain $user
* #return UserAddress
*/
public function setUser(\Site\UserBundle\Entity\UserMain $user = null)
{
$this->User = $user;
return $this;
}
/**
* Get User
*
* #return \Site\UserBundle\Entity\UserMain
*/
public function getUser()
{
return $this->User;
}
/**
* Set UserAddressType
*
* #param \Site\UserBundle\Entity\UserAddressType $userAddressType
* #return UserAddress
*/
public function setUserAddressType(\Site\UserBundle\Entity\UserAddressType $userAddressType = null)
{
$this->UserAddressType = $userAddressType;
return $this;
}
/**
* Get UserAddressType
*
* #return \Site\UserBundle\Entity\UserAddressType
*/
public function getUserAddressType()
{
return $this->UserAddressType;
}
}
The form is:
namespace Site\UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Doctrine\ORM\EntityRepository;
class UserAddressType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('UserId','hidden')
->add('LevelId', 'integer', array(
'label'=>'Sort Rate (Order)'
))
->add('AddressTypeId', 'entity', array(
'class'=>'SiteUserBundle:UserAddressType',
'query_builder'=> function(EntityRepository $er){
return $er->createQueryBuilder('t')
->orderBy('t.AddressDescription', 'ASC');
},
'property'=>'AddressDescription',
'label'=>'Address Type'
))
->add('AddressData', 'text')
->add('PublicYN', 'choice', array(
'choices' => array( 'false'=>'Private', 'true'=>'Public'),
'required'=>true,
'label'=>'Pubicly Visable'
))
->add('PrimaryYN', 'choice', array(
'choices' => array( 'false'=>'Secondary', 'true'=>'Primary'),
'required'=>true,
'label'=>'Primary Contact',
))
->add('save', 'submit', array(
'label'=>'Add Address',
'attr'=>array(
'class'=>'btn btn-primary',
),
))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Site\UserBundle\Entity\UserAddress',
'csrf_protection'=>false,
));
}
/**
* #return string
*/
public function getName()
{
return 'Create_User_Address';
}
}
Controller Function is: (I'm using fosrestbundle)
public function newAddressAction($userid, Request $request)
{
$statusCode = 201;
$address = new UserAddress();
$address->setUserId($userid);
$form = $this->createForm( new UserAddressType(), $address, array(
'method'=>'GET',
));
$form->handleRequest($request);
if($form->isValid()){
$em = $this->getDoctrine()->getManager();
$em->persist($address);
$em->flush();
return new Response('User Added to system');
}
return $this->render('SiteUserBundle:UserAddress:newUserAddress.html.twig', array(
'form' => $form->createView(),
));
}
The Twig template is very simple. All the data is posted correctly to the server: (Query String Parameters )
Create_User_Address[LevelId]:0
Create_User_Address[AddressTypeId]:5
Create_User_Address[AddressData]:555-555-5555
Create_User_Address[PublicYN]:false
Create_User_Address[PrimaryYN]:false
Create_User_Address[save]:
Create_User_Address[UserId]:3
but i keep getting the following error:
An exception occurred while executing 'INSERT INTO user_address (user_id, level_id, address_type_id, address_data, public_yn, primary_yn) VALUES (?, ?, ?, ?, ?, ?)' with params [null, 0, null, "555-555-5555", "false", "false"]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'user_id' cannot be null
As you can see the UserID and AddressTypeId fields are not mapping from the form to the Entity. I have looked over the code for all 3 pieces over and ove and for the life of me i can't see where the mismatch is happening. I did at one point change the names of those two fields in the Entity but i deleted all the getters and setters and regenerated them as well as clear the dev cache.
My hunch is there is a file somewhere in Symfony2 there is a mapping class that is wrong but i can't find it..
Thanks all
EDIT:
I tried clearing the doctrine cache as stated here: Symfony2 doctrine clear cache .
app/console doctrine:cache:clear-metadata
app/console doctrine:cache:clear-query
app/console doctrine:cache:clear-result
this resulted in the same error being generated,so the cache issue may be off the table.
EDIT:
As per Isaac's suggestion i removed ->add('UserId', 'hidden') . The form still posted with the same error message. The field is being generated correctly to the page;
<input type="hidden" id="Create_User_Address_UserId" name="Create_User_Address[UserId]" class=" form-control" value="3">
and as you can see from the Query Parameters above being posted back to the server correctly.
EDIT:
I tracked the issue down to the User and UserAddressType variables. If i remove these two variables and their getters and setters the form works perfectly without other modifications of my code. I should note that these two variables are joins to other entities. Some how they seem to be wiping out the data being submitted by the forms.
Remove
->add('UserId','hidden')
It's probably overwriting the UserId with null since it's hidden and has no value
As per lsouza suggestion I had to create a data transformer.
namespace Site\UserBundle\Form\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;
use Site\UserBundle\Entity\UserAddressType;
class AddressTypeToNumber implements DataTransformerInterface
{
/**
* #var ObjectManager
*/
private $om;
/**
* #param ObjectManager $om
*/
public function __construct(ObjectManager $om)
{
$this->om = $om;
}
/**
* Transforms an object(val) to a string
*
* #param UserAddressType|null $val
* #return string
*/
public function transform($val)
{
if (null === $val) {
return "";
}
return array();
}
/**
* Transfers a string to an object (UserAddressType)
*
* #param string $val
* #return UserAddressType|null
* #throws TransformationFailedException if object is not found
*/
public function reverseTransform($val)
{
if (!$val) {
return null;
}
$addId = $this->om
->getRepository('SiteUserBundle:UserAddressType')
->findOneBy(array('AddressTypeId' => $val));
if (null === $addId) {
throw new TransformationFailedException(sprintf(
'An Address Type with the ID of "%s" does not exsist in the system',
$val
));
}
return $addId;
}
}
Please note that the Transformer function is currently returning null but this should return a value that can be used by the form.
Some other notes that may help others are that the form class needs to be changed as well.
The setDefaultOptions function needs the following added to the $resolver variable:
->setRequired(array(
'em',
))
->setAllowedTypes(array(
'em'=>'Doctrine\Common\Persistence\ObjectManager',
));
The buildForm function needs to be changed slightly to accept the em option:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$em = $options['em'];
$transformer = new AddressTypeToNumber($em);
The field needs to be change to the varrable that holds the relationship in the Entity and not the field that is use in the link:
->add(
$builder->create('UserAddressType', 'entity', array(
'class' => 'SiteUserBundle:UserAddressType',
'property' => 'AddressDescription',
'label' => 'Address Type'
))
->addModelTransformer($transformer)
)
Finally in your controller you need to pass an instance of $this->getDoctrine()->getManager() to the form class:
$form = $this->createForm( new UserAddressType(), $address, array(
'em' => $this->getDoctrine()->getManager(),
));
I hope this helps others.

Select categories related to current Store entity

I have two entities Store and Category and each Store has it's own categories.
I'd like that when a Store owner's try to add a new category and category_parent, just the categories related to current Store will be displayed.
Right now, all categories are displayed in the select-option.
I'm using Tree Gedmo extension to manage Category entity and I use getChildrenQueryBuilder method to select categories.
How can I modify this method and add my specific constraint ?
$store which is the constraint is declared in the controller action down.
I'd like te set current Category option disabled when he try to add a category_parent, so category and category parent must be differnt.
I hope it's clear
CategoryType.php
<?php
namespace Project\StoreBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
class CategoryType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
//..........
//..........
->add('category', 'entity', array(
'required' => false,
'label' => 'Category parent',
'class' => 'ProjectStoreBundle:Category',
'attr' => array('class' => 'col-sm-8'),
'empty_value' => 'Select one category',
'property' => 'indentedName',
'multiple' => false,
'expanded' => false ,
'query_builder' => function (\Project\StoreBundle\Entity\CategoryRepository $r)
{
return $r->getChildrenQueryBuilder(null, null, 'root', 'asc', false);
}
))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Project\StoreBundle\Entity\Category'
));
}
/**
* #return string
*/
public function getName()
{
return 'project_storebundle_category';
}
}
Entity/Category.php
<?php
namespace Project\StoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Category
* #Gedmo\Tree(type="nested")
* #ORM\Table()
* #ORM\Entity(repositoryClass="Project\StoreBundle\Entity\CategoryRepository")
* #ORM\HasLifeCycleCallbacks()
*/
class Category
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*
*#Assert\NotBlank(message="Please enter the name of categorie.")
*/
private $name;
/**
* #Gedmo\slug(fields={"name"}, unique_base="uniqueBase")
* #ORM\Column(name="slug",length=255, unique=false)
*/
private $slug ;
/**
* #ORM\Column(name="uniqueBase", type="integer")
*/
private $uniqueBase ;
/**
* #ORM\Column(name="description", type="text", nullable=true)
*/
private $description;
/**
* #ORM\Column(name="metaDescription", type="string", length=255, nullable=true)
*
* #Assert\Length(
* max=255,
* maxMessage="message"
* )
*/
private $metaDescription;
/**
* #ORM\Column(name="metaKeywords", type="string", length=255, nullable=true)
*
* #Assert\Length(
* max=255,
* maxMessage="message"
* )
*/
private $metaKeywords;
/**
* #ORM\Column(name="enabled", type="boolean", nullable=false)
*/
private $enabled;
/**
* #Gedmo\TreeLeft
* #ORM\Column(name="lft", type="integer")
*/
private $lft;
/**
* #Gedmo\TreeLevel
* #ORM\Column(name="lvl", type="integer")
*/
private $lvl;
/**
* #Gedmo\TreeRight
* #ORM\Column(name="rgt", type="integer")
*/
private $rgt;
/**
* #Gedmo\TreeRoot
* #ORM\Column(name="root", type="integer", nullable=true)
*/
private $root;
/**
* #Gedmo\TreeParent
* #ORM\ManyToOne(targetEntity="Category", inversedBy="children")
* #ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $parent;
/**
* #ORM\OneToMany(targetEntity="Category", mappedBy="parent")
* #ORM\OrderBy({"lft" = "ASC"})
*/
private $children;
/**
*non mapped property
*/
private $indentedName;
/**
*non mapped property
*/
private $category;
/**
* #ORM\ManyToOne(targetEntity="Project\StoreBundle\Entity\Store", inversedBy="categories", cascade={"persist"})
* #ORM\JoinColumn(nullable=false)
*/
private $store ;
/**
* Constructor
*/
public function __construct()
{
$this->children = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Category
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set slug
*
* #param string $slug
* #return Category
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* #return string
*/
public function getSlug()
{
return $this->slug;
}
/**
* Set uniqueBase
*
* #param integer $uniqueBase
* #return Category
*/
public function setUniqueBase($uniqueBase)
{
$this->uniqueBase = $uniqueBase;
return $this;
}
/**
* Get uniqueBase
*
* #return integer
*/
public function getUniqueBase()
{
return $this->uniqueBase;
}
/**
* Set description
*
* #param string $description
* #return Category
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set metaDescription
*
* #param string $metaDescription
* #return Category
*/
public function setMetaDescription($metaDescription)
{
$this->metaDescription = $metaDescription;
return $this;
}
/**
* Get metaDescription
*
* #return string
*/
public function getMetaDescription()
{
return $this->metaDescription;
}
/**
* Set metaKeywords
*
* #param string $metaKeywords
* #return Category
*/
public function setMetaKeywords($metaKeywords)
{
$this->metaKeywords = $metaKeywords;
return $this;
}
/**
* Get metaKeywords
*
* #return string
*/
public function getMetaKeywords()
{
return $this->metaKeywords;
}
/**
* Set enabled
*
* #param boolean $enabled
* #return Category
*/
public function setEnabled($enabled)
{
$this->enabled = $enabled;
return $this;
}
/**
* Get enabled
*
* #return boolean
*/
public function getEnabled()
{
return $this->enabled;
}
/**
* Set parent
*
* #param \Project\StoreBundle\Entity\Category $parent
* #return Category
*/
public function setParent(\Project\StoreBundle\Entity\Category $parent = null)
{
$this->parent = $parent;
return $this;
}
/**
* Get parent
*
* #return \Project\StoreBundle\Entity\Category
*/
public function getParent()
{
return $this->parent;
}
/**
* Set lft
*
* #param integer $lft
* #return Category
*/
public function setLft($lft)
{
$this->lft = $lft;
return $this;
}
/**
* Get lft
*
* #return integer
*/
public function getLft()
{
return $this->lft;
}
/**
* Set lvl
*
* #param integer $lvl
* #return Category
*/
public function setLvl($lvl)
{
$this->lvl = $lvl;
return $this;
}
/**
* Get lvl
*
* #return integer
*/
public function getLvl()
{
return $this->lvl;
}
/**
* Set rgt
*
* #param integer $rgt
* #return Category
*/
public function setRgt($rgt)
{
$this->rgt = $rgt;
return $this;
}
/**
* Get rgt
*
* #return integer
*/
public function getRgt()
{
return $this->rgt;
}
/**
* Set root
*
* #param integer $root
* #return Category
*/
public function setRoot($root)
{
$this->root = $root;
return $this;
}
/**
* Get root
*
* #return integer
*/
public function getRoot()
{
return $this->root;
}
/**
* Add children
*
* #param \Project\StoreBundle\Entity\Category $children
* #return Category
*/
public function addChild(\Project\StoreBundle\Entity\Category $children)
{
$this->children[] = $children;
return $this;
}
/**
* Remove children
*
* #param \Project\StoreBundle\Entity\Category $children
*/
public function removeChild(\Project\StoreBundle\Entity\Category $children)
{
$this->children->removeElement($children);
}
/**
* Get children
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getChildren()
{
return $this->children;
}
/**
* Get IndentedName
*
*/
public function getIndentedName()
{
return str_repeat("-----", $this->lvl).$this->name;
}
/**
* Get category
*
*/
public function getCategory()
{
return $this->category;
}
/**
* Set store
*
* #param \Project\StoreBundle\Entity\Store $store
* #return Category
*/
public function setStore(\Project\StoreBundle\Entity\Store $store = null)
{
$this->store = $store;
return $this;
}
/**
* Get store
*
* #return \Project\StoreBundle\Entity\Store
*/
public function getStore()
{
return $this->store;
}
}
Controller
/**
* Create a new Category entity.
*
*/
/**
* #ParamConverter("store", options={"mapping": {"store_id":"id"}})
*/
public function newAction(Store $store)
{
// keep in mind, this will call all registered security voters
if (false === $this->get('security.context')->isGranted('edit', $store)) {
throw new AccessDeniedException('Unauthorised access!');
}
$category = new Category();
$category->setStore($store);
$category->setUniqueBase($store->getId());
$form = $this->createForm(new CategoryType(), $category);
$request = $this->getRequest();
if ($request->getMethod() == 'POST')
{
$form->bind($request);
if ($form->isValid())
{
$em = $this->getDoctrine()->getManager();
$em->persist($category);
$em->flush();
$this->get('session')->getFlashBag()->add('message', 'Category enregistred');
return $this->redirect( $this->generateUrl('dashboard_category_index', array('store_id' => $store->getId())));
}
}
return $this->render('ProjectDashboardBundle:Category:new.html.twig',
array(
'form' => $form->createView() ,
'store' =>$store,
));
}
I managed to pass the parameter $store to the form, but I don't know how to use it as a constraint in getChildrenQueryBuilder method.
Should I create a new custom method? I prefer to use getChildrenQueryBuilder if it is possible.
Here is the new code
CategoryType.php
class CategoryType extends AbstractType
{
private $store;
public function __construct($store)
{
$this->store = $store;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$store = $this->store;
$builder
//...........
//...........
->add('parent', 'entity', array(
'required' => false,
'label' => 'Category parent',
'class' => 'ProjectStoreBundle:Category',
'attr' => array('class' => 'col-sm-8'),
'empty_value' => 'Select one category',
'property' => 'indentedName',
'multiple' => false,
'expanded' => false ,
'query_builder' => function (\Project\StoreBundle\Entity\CategoryRepository $r) use ($store)
{
return $r->getChildrenQueryBuilder(null, null, 'root', 'asc', false);
}
))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Project\StoreBundle\Entity\Category'
));
}
/**
* #return string
*/
public function getName()
{
return 'project_storebundle_category';
}
}
Controller
/**
* #ParamConverter("store", options={"mapping": {"store_id":"id"}})
*/
public function newAction(Store $store)
{
// keep in mind, this will call all registered security voters
if (false === $this->get('security.context')->isGranted('edit', $store)) {
throw new AccessDeniedException('Unauthorised access!');
}
$category = new Category();
$category->setStore($store);
$category->setUniqueBase($store->getId());
$form = $this->createForm(new CategoryType($store), $category);
$request = $this->getRequest();
if ($request->getMethod() == 'POST')
{
$form->bind($request);
if ($form->isValid())
{
$em = $this->getDoctrine()->getManager();
$em->persist($category);
$em->flush();
$this->get('session')->getFlashBag()->add('message', 'Category enregistred');
return $this->redirect( $this->generateUrl('dashboard_category_index', array('store_id' => $store->getId())));
}
}
return $this->render('ProjectDashboardBundle:Category:new.html.twig',
array(
'form' => $form->createView() ,
'store' =>$store,
));
}
You're not saying which Symfony2 version you're using, but generically speaking, you just need to find a way to pass the current store to your form builder and use it in the method that filters the possible categories.
Take a look at this one, or this one, basically you just need to inject the $store into your form builder, and then you (almost) have it :-)

Categories