Symfony error when inserting new entity data - symfony

I am a beginner learning Symfony. I have an entity called sale for which I a form for inserting sales data.
The problem is each attempt to insert data results in the following error:
Neither the property "selectedstock" nor one of the methods
"addSelectedstock()"/"removeSelectedstock()", "setSelectedstock()",
"selectedstock()", "__set()" or "__call()" exist and have public
access in class "iCerge\Salesdeck\SalesBundle\Entity\Sale".
My Sale class is as follows:
<?php
namespace iCerge\Salesdeck\SalesBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Sales
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="iCerge\Salesdeck\SalesBundle\Entity\SalesRepository")
*/
class Sale
{
private $selectedstock;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var float
*
* #ORM\Column(name="cost", type="float")
*/
private $cost;
/**
* #var float
*
* #ORM\Column(name="profitloss", type="float")
*/
private $profitloss;
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="datetime")
*/
private $date;
/**
* #ORM\ManyToOne(targetEntity="iCerge\Salesdeck\StockBundle\Entity\Stock", inversedBy="sales")
* #ORM\JoinColumn(name="sid", referencedColumnName="id")
*/
protected $stock;
/**
* #var integer
*
* #ORM\Column(name="number_of_purchases", type="integer")
*/
private $number_of_purchases;
/**
* #var float
*
* #ORM\Column(name="active_buy_price", type="float")
*/
private $active_buy_price;
/**
* #var integer
*
* #ORM\Column(name="sid", type="integer")
*/
private $sid;
/**
* Get sid
*
* #return integer
*/
public function getSid()
{
return $this->sid ? $this->sid : 0;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set cost
*
* #param float $cost
* #return Sales
*/
public function setCost($cost)
{
$this->cost = $cost;
return $this;
}
/**
* Get cost
*
* #return float
*/
public function getCost()
{
return $this->cost;
}
/**
* Set date
*
* #param \DateTime $date
* #return Sales
*/
public function setDate($date)
{
$this->date = $date;
return $this;
}
/**
* Get date
*
* #return \DateTime
*/
public function getDate()
{
return $this->date;
}
/**
* Set profitloss
*
* #param float $profitloss
* #return Sales
*/
public function setProfitloss($profitloss)
{
$this->profitloss = $profitloss;
return $this;
}
/**
* Get profitloss
*
* #return float
*/
public function getProfitloss()
{
return $this->profitloss;
}
/**
* Set stock
*
* #param \iCerge\Salesdeck\StockBundle\Entity\Stock $stock
* #return Sale
*/
public function setStock(\iCerge\Salesdeck\StockBundle\Entity\Stock $stock = null)
{
$this->stock = $stock;
return $this;
}
/**
* Get stock
*
* #return \iCerge\Salesdeck\StockBundle\Entity\Stock
*/
public function getStock()
{
return $this->stock;
}
/********************/
/**
* Set number_of_purchases
*
* #return integer
*/
public function setNumberOfPurchases($purchases)
{
$this->number_of_purchases = $purchases;
return $this;
}
/**
* Get number_of_purchases
*
* #return integer
*/
public function getNumberOfPurchases()
{
return $this->number_of_purchases;
}
/**
* Set active_buy_price
*
* #return integer
*/
public function setActiveBuyPrice($price)
{
$this->active_buy_price = $price;
return $this;
}
/**
* Get active_buy_price
*
* #return integer
*/
public function getActiveBuyPrice()
{
return $this->active_buy_price;
}
public function getselectedstock()
{
return $this->selectedstock;
}
}
And the following is my Form class:
<?php
namespace iCerge\Salesdeck\SalesBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class SalesType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('selectedstock', 'choice', array(
'choices' => $options['allow_extra_fields'],
'required' => true,
'empty_value' => 'Choose a Product',
'empty_data' => null,
'label' => 'Select Item',
// 'mapped'=>false
))
/*->add('test', 'choice', array(
'choices' => $options['allow_extra_fields'],
'required' => false,
'empty_value' => 'Choose your gender',
'empty_data' => null,
'mapped'=>false
))*/
->add('number_of_purchases', 'integer', array('label'=>'Number of purchases'))
->add('cost')
->add('profitloss', 'text', array('label'=>'Profit/Loss'))
->add('date', 'datetime', array('data'=>new \DateTime('now')))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
// 'data_class' => 'iCerge\Salesdeck\SalesBundle\Entity\Sales'
'data_class' => 'iCerge\Salesdeck\SalesBundle\Entity\Sale'
));
}
/**
* #return string
*/
public function getName()
{
return 'icerge_salesdeck_salesbundle_sales';
}
}
What am I doing wrong here?
Update
Screenshot shows dropdown list of available stock.
The form is the sales/add form which requires an item of available stock from the list to be selected.

You don't have a setter for selectedstock, and not related to the error you don't have annotation to mark selectedstock as an orm column, so it won't be persisted.

Related

error in symfony for manyToOne and form imbricated

I encountered a problem under symfony3 which has blocked me for a while ... I do not understand this error:
Expected value of type "Doctrine\Common\Collections\Collection|array" for association field "AppBundle\Entity\Project#$participants", got "string" instead.
Here is my entity Project:
class Project
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="projects")
* #ORM\JoinColumn(nullable=false)
*/
private $user;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Participant", mappedBy="project", cascade={"persist", "remove"})
*/
private $participants;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var string
*
* #ORM\Column(name="content", type="text", nullable=true)
*/
private $content;
/**
* #var string
*
* #ORM\Column(name="place", type="string", length=255, nullable=true)
*/
private $place;
/**
* #var \DateTime
*
* #ORM\Column(name="dateEvent", type="datetime", nullable=true)
*/
private $dateEvent;
/**
* #var boolean
*
* #ORM\Column(name="status", type="boolean")
*/
private $status;
/**
* #var boolean
*
* #ORM\Column(name="in_progress", type="boolean")
*/
private $inProgress;
/**
* #var boolean
*
* #ORM\Column(name="accept_list", type="boolean")
*/
private $acceptList;
/**
* #var boolean
*
* #ORM\Column(name="visible_list", type="boolean")
*/
private $visibleList;
/**
* #var boolean
*
* #ORM\Column(name="many_loop", type="boolean")
*/
private $manyLoop;
/**
* #var string
*
* #ORM\Column(name="text_email", type="text", nullable=true)
*/
private $textEmail;
/**
* #var \DateTime
*
* #ORM\Column(name="created", type="datetime")
*/
private $created;
public function __construct()
{
$this->run = false;
$this->status = false;
$this->acceptList = true;
$this->visibleList = true;
$this->inProgress = false;
$this->manyLoop = true;
$this->created = new \Datetime('now');
$this->participants = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* #param string $title
*
* #return Project
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set content
*
* #param string $content
*
* #return Project
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* Get content
*
* #return string
*/
public function getContent()
{
return $this->content;
}
/**
* Set place
*
* #param string $place
*
* #return Project
*/
public function setPlace($place)
{
$this->place = $place;
return $this;
}
/**
* Get place
*
* #return string
*/
public function getPlace()
{
return $this->place;
}
/**
* Set dateEvent
*
* #param \DateTime $dateEvent
*
* #return Project
*/
public function setDateEvent($dateEvent)
{
$this->dateEvent = $dateEvent;
return $this;
}
/**
* Get dateEvent
*
* #return \DateTime
*/
public function getDateEvent()
{
return $this->dateEvent;
}
/**
* Set status
*
* #param boolean $status
*
* #return Project
*/
public function setStatus($status)
{
$this->status = $status;
return $this;
}
/**
* Get status
*
* #return boolean
*/
public function getStatus()
{
return $this->status;
}
/**
* Set inProgress
*
* #param boolean $inProgress
*
* #return Project
*/
public function setInProgress($inProgress)
{
$this->inProgress = $inProgress;
return $this;
}
/**
* Get inProgress
*
* #return boolean
*/
public function getInProgress()
{
return $this->inProgress;
}
/**
* Set acceptList
*
* #param boolean $acceptList
*
* #return Project
*/
public function setAcceptList($acceptList)
{
$this->acceptList = $acceptList;
return $this;
}
/**
* Get acceptList
*
* #return boolean
*/
public function getAcceptList()
{
return $this->acceptList;
}
/**
* Set visibleList
*
* #param boolean $visibleList
*
* #return Project
*/
public function setVisibleList($visibleList)
{
$this->visibleList = $visibleList;
return $this;
}
/**
* Get visibleList
*
* #return boolean
*/
public function getVisibleList()
{
return $this->visibleList;
}
/**
* Set manyLoop
*
* #param boolean $manyLoop
*
* #return Project
*/
public function setManyLoop($manyLoop)
{
$this->manyLoop = $manyLoop;
return $this;
}
/**
* Get manyLoop
*
* #return boolean
*/
public function getManyLoop()
{
return $this->manyLoop;
}
/**
* Set textEmail
*
* #param string $textEmail
*
* #return Project
*/
public function setTextEmail($textEmail)
{
$this->textEmail = $textEmail;
return $this;
}
/**
* Get textEmail
*
* #return string
*/
public function getTextEmail()
{
return $this->textEmail;
}
/**
* Set created
*
* #param \DateTime $created
*
* #return Project
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* #return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set user
*
* #param \AppBundle\Entity\User $user
*
* #return Project
*/
public function setUser(\AppBundle\Entity\User $user)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return \AppBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
/**
* Add participant
*
* #param \AppBundle\Entity\Participant $participant
*
* #return Project
*/
public function addParticipant(\AppBundle\Entity\Participant $participant)
{
$this->participants[] = $participant;
// On lie l'annonce à la candidature
$participant->setProject($this);
return $this;
}
/**
* Remove participant
*
* #param \AppBundle\Entity\Participant $participant
*/
public function removeParticipant(\AppBundle\Entity\Participant $participant)
{
$this->participants->removeElement($participant);
}
/**
* Get participants
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getParticipants()
{
return $this->participants;
}}
My Form:
$builder ->add('participants', ParticipantType::class);
/**
* {#inheritdoc}
*/
public function configureOptions (OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Project',
'step' => 1,
));
}
Form imbricated :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('lastName', TextType::class, array(
'required' => true,
'label' => 'Nom'
))
->add('firstName', TextType::class, array(
'required' => true,
'label' => 'Prénom'
))
->add('email', EmailType::class, array(
'required' => true,
'label' => 'Adresse mail'
));
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => array('registration')
));
}
So here is to summarize my problem, I do not understand the error that Symfony returns, yet from the examples on the internet I do not see why there is a problem here ...
If someone to a solution would be top, because I blocked on this problem for a long time ...
Thank's !
Make sure that you don't forget to add : use Doctrine\Common\Collections\ArrayCollection or use $this->participants = new \Doctrine\Common\Collections\ArrayCollection();
In your FormType you should configure the participants field as a collection of Participant. It should be done using CollectionType like this:
$builder->add('participants', CollectionType::class, array(
'entry_type' => ParticipantType::class,
'allow_add' => true,
...
));
EDIT
According to your data model, the participants Field is a collection of Participant object. As you can see in the error message you presented, an array is expected. The CollectionType will always return an array of the target type.
That is why I suggest you to consider using a CollectionType in your form type. You can learn more about CollectionType here and about Symfony forms in general here

How to customise form rendering when based on entity field in symfony 2?

I have created a form based on an entity field. This form is composed of checkboxes that allow user to choose an entity (here 'car').
This works fine but I need to customize the rendering to get extra informations. Currently, the only information that is displayed is the 'id' attribute.
In my case, I would like to display extra entity informations in the form such as color, brand etc ...
Does anyone know how to proceed ?
The controller :
public function chooserAction() {
//symfony.com/doc/current/reference/forms/types/entity.html
$cars = $this->getDoctrine()
->getRepository('CarBundle:Car')
->find(1);
$formBuilder = $this->createFormBuilder();
/*
foreach ($cars as $car) {
$formBuilder->add($car->getId() ,'checkbox')->getForm();
}
*/
$formBuilder->add('cars', 'entity', array(
'class' => 'CarBundle:Car',
'property' => 'id',
'expanded' => 'true',
'multiple' => 'true',
));
$formBuilder->add('save', 'submit');
$form = $formBuilder->getForm();
$request = $this->get('request');
$form->handleRequest($request);
if ($form->isValid()) {
echo "ok";
// return $this->redirect($this->generateUrl('car_show', array('id' => $car->getId())));
}
return $this->render('CarBundle:Car:chooser.html.twig', array('form' => $form->createView()));
}
The entity :
<?php
namespace Foobar\CarBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Car
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Foobar\CarBundle\Entity\CarRepository")
*/
class Car
{
/**
* #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;
/**
* #var string
*
* #ORM\Column(name="brand", type="string", length=255)
*/
private $brand;
/**
* #var string
*
* #ORM\Column(name="color", type="string", length=255)
*/
private $color;
/**
* #var integer
*
* #ORM\Column(name="power", type="integer")
*/
private $power;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Car
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set brand
*
* #param string $brand
* #return Car
*/
public function setBrand($brand)
{
$this->brand = $brand;
return $this;
}
/**
* Get brand
*
* #return string
*/
public function getBrand()
{
return $this->brand;
}
/**
* Set color
*
* #param string $color
* #return Car
*/
public function setColor($color)
{
$this->color = $color;
return $this;
}
/**
* Get color
*
* #return string
*/
public function getColor()
{
return $this->color;
}
/**
* Set power
*
* #param integer $power
* #return Car
*/
public function setPower($power)
{
$this->power = $power;
return $this;
}
/**
* Get power
*
* #return integer
*/
public function getPower()
{
return $this->power;
}
}
The view :
car chooser
{{ form(form) }}
You could create a toString() method in your Car entity.
public function __toString()
{
return '' . $this->getName();
}
If you want more thinks like pictures you could follow that http://symfony.com/doc/current/cookbook/form/form_customization.html

Odd many-to-many form rendering with symfony and doctrine

I'm hoping this is possible using some built-in libraries such as the form builder. I have the following three entities. The one in the middle is almost just a regular join table but it has an extra column with an extra piece of data.
Formula --< FormulaColor >-- Color
FormulaColor has the fields: formula, color, and percentage.
The percentage field is to say what percentage a color makes up of a given formula. A very simple example is that a Formula may be 77% red and 33% blue. My problem is that I want to choose the colors for a Formula, and give them a percentage manually using forms. So I would add (or edit) a certain formula and give it say the color violet (20%) green (45%) and yellow (35%). I do not care about being able to add new colors in the formula add/edit view. I just want to be able to select existing colors. I've been playing around with it for hours with collection and entity types, but no luck.
Got any pointers or tips for me? Will I have to do it manually without the form component etc?
Thanks.
formula form type
class FormulaAddEditType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('code', null, array(
'label' => 'Code'
))
->add('name', null, array(
'label' => 'Name'
))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Prism\Portal\CommonBundle\Entity\Formula'
));
}
public function getName()
{
return 'prism_portal_adminbundle_formulaaddedittype';
}
}
Formula Entity
class Formula
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*
* #Serializer\Expose
*/
private $id;
/**
* #var string $code
*
* #ORM\Column(name="code", type="string", length=50, nullable=true)
*
* #Serializer\Expose
*/
private $code;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=50, nullable=true)
*/
private $name;
/**
* #var datetime $createdOn
*
* #Gedmo\Timestampable(on="create")
* #ORM\Column(name="createdOn", type="datetime", nullable=true)
*/
private $createdOn;
/**
* #var datetime $updatedOn
*
* #Gedmo\Timestampable(on="update")
* #ORM\Column(name="updatedOn", type="datetime", nullable=true)
*/
private $updatedOn;
/**
* #var formulaColors
*
* #ORM\OneToMany(targetEntity="FormulaColor", mappedBy="formula")
*/
private $formulaColors;
public function __construct()
{
$this->formulaColors = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set code
*
* #param string $code
*/
public function setCode($code)
{
$this->code = $code;
}
/**
* Get code
*
* #return string
*/
public function getCode()
{
return $this->code;
}
/**
* Set name
*
* #param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set createdOn
*
* #param datetime $createdOn
*/
public function setCreatedOn($createdOn)
{
$this->createdOn = $createdOn;
}
/**
* Get createdOn
*
* #return datetime
*/
public function getCreatedOn()
{
return $this->createdOn;
}
/**
* Set updatedOn
*
* #param datetime $updatedOn
*/
public function setUpdatedOn($updatedOn)
{
$this->updatedOn = $updatedOn;
}
/**
* Get updatedOn
*
* #return datetime
*/
public function getUpdatedOn()
{
return $this->updatedOn;
}
/**
* Add formulaColor
*
* #param FormulaColor $formulaColor
*/
public function addFormulaColor(FormulaColor $formulaColor)
{
$this->formulaColors[] = $formulaColor;
}
/**
* Get formulaColors
*
* #return Doctrine\Common\Collections\Collection
*/
public function getFormulaColors()
{
return $this->formulaColors;
}
}
FormulaColor Entity
/**
* Prism\Portal\CommonBundle\Entity\FormulaColor
*
* #ORM\Table(name="FormulaColor")
* #ORM\Entity
*
* #Serializer\ExclusionPolicy("all")
*/
class FormulaColor
{
/**
* #var integer $formula
*
* #ORM\ManyToOne(targetEntity="Formula", inversedBy="formulaColors")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="formulaId", referencedColumnName="id")
* })
* #ORM\Id
*/
private $formula;
/**
* #var integer color
*
* #ORM\ManyToOne(targetEntity="Color", inversedBy="formulaColors")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="colorId", referencedColumnName="id")
* })
* #ORM\Id
*/
private $color;
/**
* #var decimal percentage
*
* #ORM\Column(type="decimal", precision=5, scale=2, nullable=false)
*/
private $percentage;
/**
* Set percentage
*
* #param decimal $percentage
*/
public function setPercentage($percentage)
{
$this->percentage = $percentage;
}
/**
* Get percentage
*
* #return decimal
*/
public function getPercentage()
{
return $this->percentage;
}
/**
* Set formula
*
* #param Prism\Portal\CommonBundle\Entity\Formula $formula
*/
public function setFormula(\Prism\Portal\CommonBundle\Entity\Formula $formula)
{
$this->formula = $formula;
}
/**
* Get formula
*
* #return Prism\Portal\CommonBundle\Entity\Formula
*/
public function getFormula()
{
return $this->formula;
}
/**
* Set color
*
* #param Prism\Portal\CommonBundle\Entity\Color $color
*/
public function setColor(\Prism\Portal\CommonBundle\Entity\Color $color)
{
$this->color = $color;
}
/**
* Get color
*
* #return Prism\Portal\CommonBundle\Entity\Color
*/
public function getColor()
{
return $this->color;
}
}
Color Entity
/**
* Prism\Portal\CommonBundle\Entity\Color
*
* #ORM\Table(name="Color")
* #ORM\Entity
*
* #Serializer\ExclusionPolicy("all")
*/
class Color
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string $code
*
* #ORM\Column(name="code", type="string", length=50, nullable=true)
*/
private $code;
/**
* #var string $hexColor
*
* #ORM\Column(name="hex_color", type="string", length=50, nullable=true)
*/
private $hexColor;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=50, nullable=true)
*/
private $name;
/**
* #var integer $sortOrder
*
* #ORM\Column(name="sortOrder", type="integer", nullable=true)
*/
private $sortOrder;
/**
* #var datetime $createdOn
*
* #ORM\Column(name="createdOn", type="datetime", nullable=true)
*/
private $createdOn;
/**
* #var datetime $updatedOn
*
* #ORM\Column(name="updatedOn", type="datetime", nullable=true)
*/
private $updatedOn;
/**
* #var $formulaColors
*
* #ORM\OneToMany(targetEntity="FormulaColor", mappedBy="color")
*/
private $formulaColors;
public function __construct()
{
$this->formulaColors = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set code
*
* #param string $code
*/
public function setCode($code)
{
$this->code = $code;
}
/**
* Get code
*
* #return string
*/
public function getCode()
{
return $this->code;
}
/**
* Set name
*
* #param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set sortOrder
*
* #param integer $sortOrder
*/
public function setSortOrder($sortOrder)
{
$this->sortOrder = $sortOrder;
}
/**
* Get sortOrder
*
* #return integer
*/
public function getSortOrder()
{
return $this->sortOrder;
}
/**
* Set createdOn
*
* #param datetime $createdOn
*/
public function setCreatedOn($createdOn)
{
$this->createdOn = $createdOn;
}
/**
* Get createdOn
*
* #return datetime
*/
public function getCreatedOn()
{
return $this->createdOn;
}
/**
* Set updatedOn
*
* #param datetime $updatedOn
*/
public function setUpdatedOn($updatedOn)
{
$this->updatedOn = $updatedOn;
}
/**
* Get updatedOn
*
* #return datetime
*/
public function getUpdatedOn()
{
return $this->updatedOn;
}
/**
* Get formulaColors
*
* #return Doctrine\Common\Collections\Collection
*/
public function getFormulaColors()
{
return $this->formulaColors;
}
/**
* addFormulaColors
*
* #param \Prism\Portal\CommonBundle\Entity\FormulaColor $formulaColor
*/
public function addFormulaColor(\Prism\Portal\CommonBundle\Entity\FormulaColor $formulaColor)
{
$this->formulaColors[] = $formulaColor;
}
/**
* Remove formulaColors
*
* #param \Prism\Portal\CommonBundle\Entity\FormulaColor $formulaColors
*/
public function removeFormulaColor(\Prism\Portal\CommonBundle\Entity\FormulaColor $formulaColors)
{
$this->formulaColors->removeElement($formulaColors);
}
/**
* Set hexColor
*
* #param string $hexColor
* #return Color
*/
public function setHexColor($hexColor)
{
$this->hexColor = $hexColor;
return $this;
}
/**
* Get hexColor
*
* #return string
*/
public function getHexColor()
{
return $this->hexColor;
}
}
I also have a ColorAddEditType form
class ColorAddEditType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('code', null, array(
'label' => 'Code'
))
->add('name', null, array(
'label' => 'Name'
))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Prism\Portal\CommonBundle\Entity\Color'
));
}
public function getName()
{
return 'prism_portal_adminbundle_coloraddedittype';
}
}
I've also updated my code according to Ryan's response.
FormulaColorType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('color', new ColorAddEditType());
$builder->add('percent', 'number');
}
FormulaAddEditType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('code', null, array(
'label' => 'Code'
))
->add('name', null, array(
'label' => 'Name'
));
$builder->add('formulaColors', 'collection', array(
'type' => new FormulaColorType(),
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
));
}
and now I'm getting use a transformer / set data_class to null exceptions. When I change the one to null, then it says I can change the other to null. When I do that it basically says to change it back. Is it normal that I should have to set up a data transformer for something like this?
Here is the current error I'm getting:
The form's view data is expected to be an instance of class
Prism\Portal\CommonBundle\Entity\Color, but is an instance of class
Prism\Portal\CommonBundle\Entity\FormulaColor. You can avoid this
error by setting the "data_class" option to null or by adding a view
transformer that transforms an instance of class
Prism\Portal\CommonBundle\Entity\FormulaColor to an instance of
Prism\Portal\CommonBundle\Entity\Color.
You should be able to do something like this. It's a fairly common pattern. The tricky bit will be the Javascript, but it won't be too bad. You might need to make your numbers add to 100 using Javascript as well.
FormulaType
public function buildForm(FormBuilder $builder, array $options) {
$builder->add('formulaColors', 'collection', array(
'type' => new FormularColorType(),
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
));
}
FormulaColorType
public function buildForm(FormBuilder $builder, array $options) {
$builder->add('color', new ColorType()); // Or similar
$builder->add('percent', 'number');
}

How I can persist an ArrayCollection to mysql?

the problem is the following:
When talking about radios I have programs, each program must have ads, so each program have one or many ads mentions.
Mi entity program:
<?php
namespace MediterraneoFM\MediterraneoFMBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* MediterraneoFM\MediterraneoFMBundle\Entity\Programas
*
* #ORM\Table()
* #ORM\Entity
*/
class Programas
{
/**
* #var integer $id_programa
*
* #ORM\Column(name="id_programa", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id_programa;
/**
* #var string $nombre
*
* #ORM\Column(name="nombre", type="string", length=40)
*/
private $nombre;
/**
* #var string $id_mencion_programa
*
* #ORM\Column(name="id_mencion_programa", type="string")
*
* #ORM\ManyToOne(targetEntity="MencionPrograma", inversedBy="Programas")
*
*/
private $id_mencion_programa;
/**
* #var \DateTime $duracion_desde
*
* #ORM\Column(name="duracion_desde", type="time")
*/
private $duracion_desde;
/**
* #var \DateTime $duracion_hasta
*
* #ORM\Column(name="duracion_hasta", type="time")
*/
private $duracion_hasta;
/**
* Get id_programa
*
* #return integer
*/
public function getIdPrograma()
{
return $this->id_programa;
}
/**
* Set nombre
*
* #param string $nombre
* #return Programas
*/
public function setNombre($nombre)
{
$this->nombre = $nombre;
return $this;
}
/**
* Get nombre
*
* #return string
*/
public function getNombre()
{
return $this->nombre;
}
/**
* Set id_mencion_programa
*
* #param MencionPrograma $idMencionPrograma
*
* #return Programas
*/
public function setIdMencionPrograma(MencionPrograma $idMencionPrograma)
{
$this->id_mencion_programa = $idMencionPrograma;
return $this;
}
/**
* Get id_mencion_programa
*
* #return string
*/
public function getIdMencionPrograma()
{
return $this->id_mencion_programa;
}
/**
* Set duracion_desde
*
* #param \DateTime $duracionDesde
* #return Programas
*/
public function setDuracionDesde($duracionDesde)
{
$this->duracion_desde = $duracionDesde;
return $this;
}
/**
* Get duracion_desde
*
* #return \DateTime
*/
public function getDuracionDesde()
{
return $this->duracion_desde;
}
/**
* Set duracion_hasta
*
* #param \DateTime $duracionHasta
* #return Programas
*/
public function setDuracionHasta($duracionHasta)
{
$this->duracion_hasta = $duracionHasta;
return $this;
}
/**
* Get duracion_hasta
*
* #return \DateTime
*/
public function getDuracionHasta()
{
return $this->duracion_hasta;
}
}
Mi entity mentions:
<?php
namespace MediterraneoFM\MediterraneoFMBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* MediterraneoFM\MediterraneoFMBundle\Entity\MencionPrograma
*
* #ORM\Table()
* #ORM\Entity
*/
class MencionPrograma
{
/**
* #var integer $id_mencion_programa
*
* #ORM\Column(name="id_mencion_programa", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\OneToMany(targetEntity="Programas", mappedBy="MencionPrograma")
*
*/
private $id_mencion_programa;
/**
* #var string $nombre
*
* #ORM\Column(name="nombre", type="string", length=33)
*/
private $nombre;
/**
* #var integer $id_emision_programa
*
* #ORM\Column(name="id_emision_programa", type="integer")
*/
private $id_emision_programa;
/**
* #var string $nro_menciones
*
* #ORM\Column(name="nro_menciones", type="string", length=11)
*/
private $nro_menciones;
public function __construct() {
$this->id_mencion_programa = new ArrayCollection();
}
/**
* Get id_mencion_programa
*
* #return integer
*/
public function getIdMencionPrograma()
{
return $this->id_mencion_programa;
}
/**
* Set id_emision_programa
*
* #param integer $idEmisionPrograma
* #return MencionPrograma
*/
public function setIdEmisionPrograma($idEmisionPrograma)
{
$this->id_emision_programa = $idEmisionPrograma;
return $this;
}
/**
* Get id_emision_programa
*
* #return integer
*/
public function getIdEmisionPrograma()
{
return $this->id_emision_programa;
}
/**
* Set nro_menciones
*
* #param string $nroMenciones
* #return MencionPrograma
*/
public function setNroMenciones($nroMenciones)
{
$this->nro_menciones = $nroMenciones;
return $this;
}
/**
* Get nro_menciones
*
* #return string
*/
public function getNroMenciones()
{
return $this->nro_menciones;
}
/**
* Set nombre
*
* #param string $nombre
* #return MencionPrograma
*/
public function setNombre($nombre)
{
$this->nombre = $nombre;
return $this;
}
/**
* Get nombre
*
* #return string
*/
public function getNombre()
{
return $this->nombre;
}
}
My controller:
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
namespace MediterraneoFM\MediterraneoFMBundle\Controller;
# Funciones del kernel de Symfony
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Doctrine\Common\Collections\ArrayCollection;
# Paginador
use MakerLabs\PagerBundle\Pager;
use MakerLabs\PagerBundle\Adapter\ArrayAdapter;
use MakerLabs\PagerBundle\Adapter\DoctrineOrmAdapter;
# Entities
use MediterraneoFM\MediterraneoFMBundle\Entity\Programas;
# Types
use MediterraneoFM\MediterraneoFMBundle\Form\InsertProgramasType;
class ProgramasController extends Controller {
# Alta de Clientes, insert en tabla Clientes.
public function insertAction() {
$programas = new Programas();
$formType = new InsertProgramasType();
$form = $this->createForm($formType, $programas);
return $this->render('MediterraneoFMBundle::insertProgramas.html.twig', array('form' => $form->createView()));
}
public function insertSuccessAction(Request $request) {
# Objeto que modifico
$programas = new Programas();
# Formulario que modifico
$formType = new InsertProgramasType();
$form = $this->createForm($formType, $programas);
if ($request->getMethod() == 'POST'):
$form->bind($request);
$data = $form->getData();
if ($form->isValid()):
$em = $this->getDoctrine()->getManager();
$em->persist($programas);
$em->flush();
return $this->redirect($this->generateUrl('insertProgramas'));
endif;
endif;
}
/**
*
* #Route("/programas/show/{limit}/{page}", defaults={"page"=1}, name="showProgramas")
*
*/
public function showAction($page, $limit) {
$programas = $this->getDoctrine()
->getRepository('MediterraneoFMBundle:Programas')
->findAll();
if (!$programas):
throw $this->createNotFoundException('No emisoras found for id ');
endif;
$adapter = new ArrayAdapter($programas);
$pager = new Pager($adapter, array('page' => $page, 'limit' => $limit));
return $this->render('MediterraneoFMBundle::showProgramas.html.twig', array('emisoras' => $programas, 'pager' => $pager));
}
}
?>
My formtype:
<?php
namespace MediterraneoFM\MediterraneoFMBundle\Form;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class InsertProgramasType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('nombre')
->add('id_mencion_programa', 'entity', array(
'class' => 'MediterraneoFM\MediterraneoFMBundle\Entity\MencionPrograma',
'property' => 'nombre',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('c');
},
'label' => 'Mencion',
'multiple' => true,
'expanded' => true,
'required' => false,
))
->add('duracion_desde', 'time', array(
'with_seconds' => true
))
->add('duracion_hasta', 'time', array(
'with_seconds' => true
))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'MediterraneoFM\MediterraneoFMBundle\Entity\Programas',
'csrf_protection' => false,
'csrf_field_name' => '_token',
// a unique key to help generate the secret token
'intention' => 'task_item',
));
}
public function getName()
{
return 'mediterraneofm_mediterraneofmbundle_insertprogramastype';
}
}
So, when I save the data to de data base, it saves this:
O:58:"MediterraneoFM\MediterraneoFMBundle\Entity\MencionPrograma":4: {s:79:"�MediterraneoFM\MediterraneoFMBundle\Entity \MencionPrograma�id_mencion_programa";i:2;s:66:"�MediterraneoFM\MediterraneoFMBundle\Entity\MencionPrograma�nombre";s:3:"8-1";s:79:"�MediterraneoFM\MediterraneoFMBundle\Entity\MencionPrograma�id_emision_programa";i:2;s:73:"�MediterraneoFM\MediterraneoFMBundle\Entity\MencionPrograma�nro_menciones";s:1:"1";}
or like this:
Doctrine\Common\Collections\ArrayCollection#0000000037e77446000000008ebafd04
What Am I doing wrong? Sorry for my english!

Symfony 2 - Multiple form fields for one database row

I'm using Symfony 2.1 and Doctrine 2.
I'm dealing with 2 main entities : Place and Feature, with a ManyToMany relationship between them.
There's many features in the database, and to group them by theme the Feature is also related to a FeatureCategory entity with a ManyToOne relationship.
Here's the code of the different entities :
The Place entity
namespace Mv\PlaceBundle\Entity;
…
/**
* Mv\PlaceBundle\Entity\Place
*
* #ORM\Table(name="place")
* #ORM\Entity(repositoryClass="Mv\PlaceBundle\Entity\Repository\PlaceRepository")
* #ORM\HasLifecycleCallbacks
*/
class Place
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=255, unique=true)
* #Assert\NotBlank
*/
private $name;
/**
* #ORM\ManyToMany(targetEntity="\Mv\MainBundle\Entity\Feature")
* #ORM\JoinTable(name="places_features",
* joinColumns={#ORM\JoinColumn(name="place_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="feature_id", referencedColumnName="id")}
* )
*/
private $features;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Place
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Add features
*
* #param \Mv\MainBundle\Entity\Feature $features
* #return Place
*/
public function addFeature(\Mv\MainBundle\Entity\Feature $features)
{
$this->features[] = $features;
echo 'Add "'.$features.'" - Total '.count($this->features).'<br />';
return $this;
}
/**
* Remove features
*
* #param \Mv\MainBundle\Entity\Feature $features
*/
public function removeFeature(\Mv\MainBundle\Entity\Feature $features)
{
$this->features->removeElement($features);
}
/**
* Get features
*
* #return Doctrine\Common\Collections\Collection
*/
public function getFeatures()
{
return $this->features;
}
public function __construct()
{
$this->features = new \Doctrine\Common\Collections\ArrayCollection();
}
The Feature Entity :
namespace Mv\MainBundle\Entity;
…
/**
* #ORM\Entity
* #ORM\Table(name="feature")
* #ORM\HasLifecycleCallbacks
*/
class Feature
{
use KrToolsTraits\PictureTrait;
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(name="label", type="string", length=255)
* #Assert\NotBlank()
*/
protected $label;
/**
* #ORM\ManyToOne(targetEntity="\Mv\MainBundle\Entity\FeatureCategory", inversedBy="features", cascade={"persist"})
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
private $category;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set label
*
* #param string $label
* #return Feature
*/
public function setLabel($label)
{
$this->label = $label;
return $this;
}
/**
* Get label
*
* #return string
*/
public function getLabel()
{
return $this->label;
}
/**
* Set category
*
* #param Mv\MainBundle\Entity\FeatureCategory $category
* #return Feature
*/
public function setCategory(\Mv\MainBundle\Entity\FeatureCategory $category = null)
{
$this->category = $category;
return $this;
}
/**
* Get category
*
* #return Mv\MainBundle\Entity\FeatureCategory
*/
public function getCategory()
{
return $this->category;
}
}
The FeatureCategory entity :
namespace Mv\MainBundle\Entity;
...
/**
* #ORM\Entity
* #ORM\Table(name="feature_category")
*/
class FeatureCategory
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(name="code", type="string", length=255)
* #Assert\NotBlank()
*/
protected $code;
/**
* #ORM\Column(name="label", type="string", length=255)
* #Assert\NotBlank()
*/
protected $label;
/**
* #ORM\OneToMany(targetEntity="\Mv\MainBundle\Entity\Feature", mappedBy="category", cascade={"persist", "remove"}, orphanRemoval=true)
* #Assert\Valid()
*/
private $features;
public function __construct()
{
$this->features = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set code
*
* #param string $code
* #return Feature
*/
public function setCode($code)
{
$this->code = $code;
return $this;
}
/**
* Get code
*
* #return string
*/
public function getCode()
{
return $this->code;
}
/**
* Set label
*
* #param string $label
* #return Feature
*/
public function setLabel($label)
{
$this->label = $label;
return $this;
}
/**
* Get label
*
* #return string
*/
public function getLabel()
{
return $this->label;
}
/**
* Add features
*
* #param \Mv\MainBundle\Entity\Feature $features
*/
public function addFeatures(\Mv\MainBundle\Entity\Feature $features){
$features->setCategory($this);
$this->features[] = $features;
}
/**
* Get features
*
* #return Doctrine\Common\Collections\Collection
*/
public function getFeatures()
{
return $this->features;
}
/*
* Set features
*/
public function setFeatures(\Doctrine\Common\Collections\Collection $features)
{
foreach ($features as $feature)
{
$feature->setCategory($this);
}
$this->features = $features;
}
/**
* Remove features
*
* #param Mv\MainBundle\Entity\Feature $features
*/
public function removeFeature(\Mv\MainBundle\Entity\Feature $features)
{
$this->features->removeElement($features);
}
/**
* Add features
*
* #param Mv\MainBundle\Entity\Feature $features
* #return FeatureCategory
*/
public function addFeature(\Mv\MainBundle\Entity\Feature $features)
{
$features->setCategory($this);
$this->features[] = $features;
}
}
Feature table is already populated, and users won't be able to add features but only to select them in a form collection to link them to the Place.
(The Feature entity is for the moment only linked to Places but will be later related to others entities from my application, and will contain all the features available for all entities)
In the Place form I need to display checkboxes of the features available for a Place, but I need to display them grouped by category.
Example :
Visits (FeatureCategory - code VIS) :
Free (Feature)
Paying (Feature)
Languages spoken (FeatureCategory - code LAN) :
English (Feature)
French (Feature)
Spanish (Feature)
My idea
Use virtual forms in my PlaceType form, like this :
$builder
->add('name')
->add('visit', new FeatureType('VIS'), array(
'data_class' => 'Mv\PlaceBundle\Entity\Place'
))
->add('language', new FeatureType('LAN'), array(
'data_class' => 'Mv\PlaceBundle\Entity\Place'
));
And create a FeatureType virtual form, like this :
class FeatureType extends AbstractType
{
protected $codeCat;
public function __construct($codeCat)
{
$this->codeCat = $codeCat;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('features', 'entity', array(
'class' => 'MvMainBundle:Feature',
'query_builder' => function(EntityRepository $er)
{
return $er->createQueryBuilder('f')
->leftJoin('f.category', 'c')
->andWhere('c.code = :codeCat')
->setParameter('codeCat', $this->codeCat)
->orderBy('f.position', 'ASC');
},
'expanded' => true,
'multiple' => true
));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'virtual' => true
));
}
public function getName()
{
return 'features';
}
}
With this solution I get what I want but the bind process doesn't persist all the features. Instead of grouping them, it only keeps me and persist the last group "language", and erases all the previouses features datas. To see it in action, if I check the 5 checkboxes, it gets well into the Place->addFeature() function 5 times, but the length of the features arrayCollection is successively : 1, 2, 1, 2, 3.
Any idea on how to do it another way ? If I need to change the model I'm still able to do it.
What is the best way, reusable on my future other entities also related to Feature, to handle this ?
Thank you guys.
I think your original need is only about templating.
So you should not tweak the form and entity persistence logic to get the desired autogenerated form.
You should go back to a basic form
$builder
->add('name')
->add('features', 'entity', array(
'class' => 'MvMainBundle:Feature',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('f')
//order by category.xxx, f.position
},
'expanded' => true,
'multiple' => true
));
And tweak your form.html.twig

Resources