I am designing an application for managing reports. I'm developing this with Symfony 3.2.6 In this picture you can see my data model. I want to do two things:
1. Create new layouts for a report with a number of given modules
2. Create instances of this reports and save them in the database
So I think this is a way to do this with this data model, isn't it? But how can I now create a form in Symfony from that?
I do something like that:
$builder
->add('name', TextType::class)
;
foreach ($options['moduleValues'] as $moduleValue)
{
if($moduleValue instanceof RangeModuleValue)
{
$builder->add('value', RangeType::class, array(
'attr' => array(
'min' => $moduleValue->getRangeModule()->getStartValue(),
'max' => $moduleValue->getRangeModule()->getEndValue()
)
));
}
}
But then I get the error:
Neither the property "value" nor one of the methods "getValue()", "value()", "isValue()", "hasValue()", "__get()" exist and have public access in class "ReportBundle\Entity\Report".
I think the error is clear, the "value" is in the table range_module_value. But how should I change my design or my Form to handle this?
Note: the parent class Module exists, because there will be other modules like "TextModule" in future.
Here is my class Report:
class Report
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #ORM\ManyToOne(targetEntity="ReportBundle\Entity\ReportLayout")
* #ORM\JoinColumn(name="layout_id", referencedColumnName="id")
*/
private $layout;
/**
* Report constructor.
* #param int $id
*/
public function __construct($layout)
{
$this->layout = $layout;
}
/**
* #return int
*/
public function getLayout()
{
return $this->layout;
}
/**
* #param int $layout
*/
public function setLayout($layout)
{
$this->layout = $layout;
}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Report
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
}
And here is the class RangeModuleValue, in which I want to persist the value of a module for a specific report.
class RangeModuleValue
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="ReportBundle\Entity\RangeModule")
* #ORM\JoinColumn(name="rangeModule_id", referencedColumnName="id")
*/
private $rangeModule;
/**
* #ORM\ManyToOne(targetEntity="ReportBundle\Entity\Report")
* #ORM\JoinColumn(name="report_id", referencedColumnName="id")
*/
private $report;
/**
* #var int
*
* #ORM\Column(name="value", type="integer")
*/
private $value;
/**
* RangeModuleValue constructor.
* #param $rangeModule
* #param $report
*/
public function __construct($report, $rangeModule)
{
$this->report = $report;
$this->rangeModule = $rangeModule;
}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set rangeModule
*
* #param string $rangeModule
*
* #return RangeModuleValue
*/
public function setRangeModule($rangeModule)
{
$this->rangeModule = $rangeModule;
return $this;
}
/**
* Get rangeModule
*
* #return string
*/
public function getRangeModule()
{
return $this->rangeModule;
}
/**
* Set report
*
* #param string $report
*
* #return RangeModuleValue
*/
public function setReport($report)
{
$this->report = $report;
return $this;
}
/**
* Get report
*
* #return string
*/
public function getReport()
{
return $this->report;
}
/**
* Set value
*
* #param integer $value
*
* #return RangeModuleValue
*/
public function setValue($value)
{
$this->value = $value;
return $this;
}
/**
* Get value
*
* #return int
*/
public function getValue()
{
return $this->value;
}
}
In class report you add this function to allow add many $rangeModule or $value :
public function addrangemodule (RangeModuleValue $rangeModule)
{
$day->setIdReport($this);
$this->ranges->add($day);
}
But ranged should be an ArrayCollection :
public function setranges(ArrayCollection $ranges)
{
$this->ranges= $ranges;
}
In Controller adds as much as you need :
$range = new RangeModuleValue();
$report->addrangemodule ($range);
This code is just an example i am not sure that he works.
For more information this is the documentation :
https://symfony.com/doc/current/form/form_collections.html
http://www.doctrine-project.org/api/common/2.3/class-Doctrine.Common.Collections.ArrayCollection.html
Related
I have a question.
I have 2 entity
/**
* #ORM\Entity
* #ORM\Table(name="call_center")
*/
class Call {
/**
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Id
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="Number", mappedBy="number")
* #ORM\Column(type="string")
*/
private $number;
/**
* #ORM\Column(type="string")
*/
private $value;
......
getters setters
/**
* #ORM\Entity
* #ORM\Table(name="number")
*/
class Number {
/**
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Id
* #ORM\Column(type="integer")
*
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Call", inversedBy="number")
* #ORM\JoinColumn(nullable=false)
*/
private $number;
/**
* #ORM\Column(type="string")
*/
private $link;
And I would like to show my data in controller.
This is my controller
class DefaultController extends Controller
{
/**
* #Route("/pl/", name="homepage")
*/
public function indexAction(Request $request)
{
$em = $this->getDoctrine()->getRepository('AppBundle:Call')->findAll();
foreach ($em as $name) {
switch(1) {
case $name->getNumber():
echo $name->getValue();
echo $name->getLink(); <----PROBLEME
break;
default:
break;
}
}
return $this->render('default/index.html.twig', array(
'em' => $name
));
}
}
Data with entity call displayed but I don't know how dipsplay data from Number (getLink()). The problem is that I have a loop in which I have to display for a particular value relationship. Probably I have to create repository for entity?
Entity Call
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set number
*
* #param string $number
*
* #return Call
*/
public function setNumber($number)
{
$this->number = $number;
return $this;
}
/**
* Get number
*
* #return string
*/
public function getNumber()
{
return $this->number;
}
/**
* Set value
*
* #param string $value
*
* #return Call
*/
public function setValue($value)
{
$this->value = $value;
return $this;
}
/**
* Get value
*
* #return string
*/
public function getValue()
{
return $this->value;
}
entity Number
/**
* Set number
*
* #param \AppBundle\Entity\Call $number
*
* #return Number
*/
public function setNumber(\AppBundle\Entity\Call $number)
{
$this->number = $number;
return $this;
}
/**
* Get number
*
* #return \AppBundle\Entity\Call
*/
public function getNumber()
{
return $this->number;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set link
*
* #param string $link
*
* #return Number
*/
public function setLink($link)
{
$this->link = $link;
return $this;
}
/**
* Get link
*
* #return string
*/
public function getLink()
{
return $this->link;
}
Maybe you have a string because you tell doctrine to put a string ?
remove the following annotation from your relation :
#ORM\Column(type="string")
Have you tried to access it via $name->getNumber()->getLink() ?
as pointed out below, by tny, you should fix your annotations, or the above will not work, as getNumber() is currently returning a string instead of a Number instance
I want to keep the previous version of an entity. When the 'old' entity is updated I want to save it with the same id but with a different revision number so it looks something like this
id: 1 revision_number: 1
id: 1 revision_number: 2
This is the entity
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Form
*
* #ORM\Table()
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
*/
class Form
{
/**
* #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="export_template", type="string", length=255, nullable = true)
*/
private $exportTemplate;
/**
* #var \DateTime
*
* #ORM\Column(name="revision", type="datetime", nullable = true)
*/
private $revision;
/**
* #var integer
*
* #ORM\Column(name="revision_number", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $revisionNumber;
/**
* #ORM\ManyToOne(targetEntity="Client", inversedBy="forms")
* #ORM\JoinColumn(name="form_id", referencedColumnName="id")
*/
protected $client;
/**
* #ORM\OneToMany(targetEntity="Section", mappedBy="form", cascade={"persist"})
*/
protected $sections;
/**
* #ORM\OneToMany(targetEntity="Inspection", mappedBy="form")
*/
protected $inspections;
public function __construct()
{
$this->sections = new ArrayCollection();
$this->inspections = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Form
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set exportTemplate
*
* #param string $exportTemplate
* #return Form
*/
public function setExportTemplate($exportTemplate)
{
$this->exportTemplate = $exportTemplate;
return $this;
}
/**
* Get exportTemplate
*
* #return string
*/
public function getExportTemplate()
{
return $this->exportTemplate;
}
/**
* Set revision
*
* #param \DateTime $revision
* #return Form
*/
public function setRevision($revision)
{
$this->revision = $revision;
return $this;
}
/**
* Get revision
*
* #return \DateTime
*/
public function getRevision()
{
return $this->revision;
}
/**
* #param $revisionNumber
* #return Form
*/
public function setRevisionNumber($revisionNumber)
{
$this->revisionNumber = $revisionNumber;
return $this;
}
/**
* #return int
*/
public function getRevisionNumber()
{
return $this->revisionNumber;
}
/**
* Set client
*
* #param \AppBundle\Entity\Client $client
* #return Form
*/
public function setClient(\AppBundle\Entity\Client $client = null)
{
$this->client = $client;
return $this;
}
/**
* Get client
*
* #return \AppBundle\Entity\Client
*/
public function getClient()
{
return $this->client;
}
/**
* Add sections
*
* #param \AppBundle\Entity\Section $sections
* #return Form
*/
public function addSection(\AppBundle\Entity\Section $sections)
{
$this->sections[] = $sections;
return $this;
}
/**
* Remove sections
*
* #param \AppBundle\Entity\Section $sections
*/
public function removeSection(\AppBundle\Entity\Section $sections)
{
$this->sections->removeElement($sections);
}
/**
* Get sections
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getSections()
{
return $this->sections;
}
/**
* Add inspections
*
* #param \AppBundle\Entity\Inspection $inspections
* #return Form
*/
public function addInspection(\AppBundle\Entity\Inspection $inspections)
{
$this->inspections[] = $inspections;
return $this;
}
/**
* Remove inspections
*
* #param \AppBundle\Entity\Inspection $inspections
*/
public function removeInspection(\AppBundle\Entity\Inspection $inspections)
{
$this->inspections->removeElement($inspections);
}
/**
* Get inspections
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getInspections()
{
return $this->inspections;
}
/**
*
* #ORM\PrePersist()
*/
public function preSetDate(){
$this->revision = new \DateTime();
}
}
Is there a way I can do what I described?
I think what you may need is Loggable extension for Doctrine. Check this link:
https://github.com/Atlantic18/DoctrineExtensions/blob/master/doc/loggable.md
Loggable behavior tracks your record changes and is able to manage versions.
Using loggable behavior you can revert version from your repository with revert() method. You can find many examples on site I gave you the link above.
If you dont fancy using a 3rd party bundle for this:
your ID's will still have to be unique. If you need to track where the copy originated from then you could add a new parameter.
Once you have decided upon this, I would simply clone it, alter the revision number and add the original id if thats which way you want to go and then persist it.
class Form {
// ....
$orig_id = null;
// any getters/setters you need
// .....
}
then in the controller:
public function copyEntity($entity) {
$new_ent = clone $entity;
$new_ent->setOrigId( $entity->getId() );
$new_ent->setRevision( true ); // I would probably bin this as origId being !== null would do the same job
$this->entityManager->persist( $new_ent );
$this->entityManager->flush();
// .....
}
I have a Property:
(Note: the legacy_id was not my doing and is now ingrained in the app so can't be changed at this time)
<?php
namespace Entity\Beaverusiv;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Entity\Beaverusiv\Property
*
* #ORM\Entity()
* #ORM\Table(name="properties", indexes={#ORM\Index(name="fk_properties_smoking_options1_idx", columns={"smoking_id"}), #ORM\Index(name="fk_properties_linen_options1_idx", columns={"linen_id"}), #ORM\Index(name="fk_properties_pets_options1_idx", columns={"pets_id"}), #ORM\Index(name="fk_properties_property_city1_idx", columns={"city_id"})})
*/
class Property
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\Column(type="integer")
*/
protected $legacy_id;
/**
* #ORM\ManyToMany(targetEntity="FeaturesOption", mappedBy="properties")
*/
protected $featuresOptions;
public function __construct()
{
$this->featuresOptions = new ArrayCollection();
}
/**
* Set the value of id.
*
* #param integer $id
* #return \Entity\Beaverusiv\Property
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Get the value of id.
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set the value of legacy_id.
*
* #param integer $legacy_id
* #return \Entity\Beaverusiv\Property
*/
public function setLegacyId($legacy_id)
{
$this->legacy_id = $legacy_id;
return $this;
}
/**
* Get the value of legacy_id.
*
* #return integer
*/
public function getLegacyId()
{
return $this->legacy_id;
}
/**
* Add FeaturesOption entity to collection.
*
* #param \Entity\Beaverusiv\FeaturesOption $featuresOption
* #return \Entity\Beaverusiv\Property
*/
public function addFeaturesOption(FeaturesOption $featuresOption)
{
$this->featuresOptions[] = $featuresOption;
return $this;
}
/**
* Get FeaturesOption entity collection.
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getFeaturesOptions()
{
return $this->featuresOptions;
}
}
And FeaturesOption:
<?php
namespace Entity\Beaverusiv;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Entity\Beaverusiv\FeaturesOption
*
* #ORM\Entity()
* #ORM\Table(name="features_options")
*/
class FeaturesOption
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="integer", nullable=true)
*/
protected $display_order;
/**
* #ORM\Column(type="string", length=200, nullable=true)
*/
protected $text;
/**
* #ORM\Column(type="integer", nullable=true)
*/
protected $status;
/**
* #ORM\ManyToMany(targetEntity="Property", inversedBy="featuresOptions")
* #ORM\JoinTable(name="properties_features",
* joinColumns={#ORM\JoinColumn(name="feature_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="property_id", referencedColumnName="id")}
* )
*/
protected $properties;
public function __construct()
{
$this->properties = new ArrayCollection();
}
/**
* Set the value of id.
*
* #param integer $id
* #return \Entity\Beaverusiv\FeaturesOption
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Get the value of id.
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set the value of display_order.
*
* #param integer $display_order
* #return \Entity\Beaverusiv\FeaturesOption
*/
public function setDisplayOrder($display_order)
{
$this->display_order = $display_order;
return $this;
}
/**
* Get the value of display_order.
*
* #return integer
*/
public function getDisplayOrder()
{
return $this->display_order;
}
/**
* Set the value of text.
*
* #param string $text
* #return \Entity\Beaverusiv\FeaturesOption
*/
public function setText($text)
{
$this->text = $text;
return $this;
}
/**
* Get the value of text.
*
* #return string
*/
public function getText()
{
return $this->text;
}
/**
* Set the value of status.
*
* #param integer $status
* #return \Entity\Beaverusiv\FeaturesOption
*/
public function setStatus($status)
{
$this->status = $status;
return $this;
}
/**
* Get the value of status.
*
* #return integer
*/
public function getStatus()
{
return $this->status;
}
/**
* Add Property entity to collection.
*
* #param \Entity\Beaverusiv\Property $property
* #return \Entity\Beaverusiv\FeaturesOption
*/
public function addProperty(Property $property)
{
$property->addFeaturesOption($this);
$this->properties[] = $property;
return $this;
}
/**
* Get Property entity collection.
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getProperties()
{
return $this->properties;
}
}
And the pivot:
<?php
namespace Entity\Beaverusiv;
use Doctrine\ORM\Mapping as ORM;
/**
* Entity\Beaverusiv\PropertiesFeature
*
* #ORM\Entity()
* #ORM\Table(name="properties_features", indexes={#ORM\Index(name="fk_properties_features_features_options1_idx", columns={"feature_id"}), #ORM\Index(name="fk_properties_features_properties1_idx", columns={"property_id"})})
*/
class PropertiesFeature
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
*/
protected $feature_id;
/**
* #ORM\Id
* #ORM\Column(type="integer")
*/
protected $property_id;
/**
* #ORM\ManyToOne(targetEntity="FeaturesOption", inversedBy="propertiesFeatures")
* #ORM\JoinColumn(name="feature_id", referencedColumnName="id", nullable=false)
*/
protected $featuresOption;
/**
* #ORM\ManyToOne(targetEntity="Property", inversedBy="propertiesFeatures")
* #ORM\JoinColumn(name="property_id", referencedColumnName="id", nullable=false)
*/
protected $property;
public function __construct()
{
}
/**
* Set the value of feature_id.
*
* #param integer $feature_id
* #return \Entity\Beaverusiv\PropertiesFeature
*/
public function setFeatureId($feature_id)
{
$this->feature_id = $feature_id;
return $this;
}
/**
* Get the value of feature_id.
*
* #return integer
*/
public function getFeatureId()
{
return $this->feature_id;
}
/**
* Set the value of property_id.
*
* #param integer $property_id
* #return \Entity\Beaverusiv\PropertiesFeature
*/
public function setPropertyId($property_id)
{
$this->property_id = $property_id;
return $this;
}
/**
* Get the value of property_id.
*
* #return integer
*/
public function getPropertyId()
{
return $this->property_id;
}
/**
* Set FeaturesOption entity (many to one).
*
* #param \Entity\Beaverusiv\FeaturesOption $featuresOption
* #return \Entity\Beaverusiv\PropertiesFeature
*/
public function setFeaturesOption(FeaturesOption $featuresOption = null)
{
$this->featuresOption = $featuresOption;
$this->feature_id = $featuresOption->getId();
return $this;
}
/**
* Get FeaturesOption entity (many to one).
*
* #return \Entity\Beaverusiv\FeaturesOption
*/
public function getFeaturesOption()
{
return $this->featuresOption;
}
/**
* Set Property entity (many to one).
*
* #param \Entity\Beaverusiv\Property $property
* #return \Entity\Beaverusiv\PropertiesFeature
*/
public function setProperty(Property $property = null)
{
$this->property = $property;
$this->property_id = $property->getLegacyId();
return $this;
}
/**
* Get Property entity (many to one).
*
* #return \Entity\Beaverusiv\Property
*/
public function getProperty()
{
return $this->property;
}
}
I am having to bring in data from an older DB, like this:
<?php
public function sync()
{
$persist_count = 0; // Keep track of home many properties are ready to be flushed
$flush_count = 20; // Persist and flush the properties in groups of...
$i = 0;
$CI =& get_instance();
$legacy_properties = null;
while ($legacy_properties !== false)
{
$legacy_properties = $this->doctrine->mssql
->getRepository('Entity\MSSQL\TblProperty')
->getProperties($i, $flush_count);
if (count($legacy_properties)===0)
{
break;
}
foreach ($legacy_properties as $legacy_property)
{
// Legacy ID
$legacy_id = $legacy_property['propertyID'];
// Lets see if this property already exists in the new database. If it does, we'll just use that.
$property = $this->doctrine->em
->getRepository('Entity\Beaverusiv\Property')
->findOneBy(array(
'legacy_id' => $legacy_id
));
// If the property from the legacy database does not exist in the new database, let's add it.
if (! $property)
{
$property = new Entity\Beaverusiv\Property; // create a new property instance
$property->setLegacyId($legacy_id);
}
// Update property details
// Set all the other Property fields
$legacy_features = $this->doctrine->mssql
->getRepository('Entity\MSSQL\TblProperty')
->findOneBy(array('propertyID' => $legacy_id))
->getTblPropertyFeaturesJoins();
foreach ($legacy_features as $legacy_feature) {
$feature_id = $legacy_feature->getTblPropertyFeature()->getFeatureID();
$feature = $this->doctrine->em
->getRepository('Entity\Beaverusiv\FeaturesOption')
->findOneBy(array(
'id' => $feature_id
));
$feature_pivot = new Entity\Beaverusiv\PropertiesFeature;
$feature_pivot->setFeaturesOption($feature);
$feature_pivot->setProperty($property);
$this->doctrine->em->merge($feature_pivot);
}
// Persist this property, ready forz flushing in groups of $persist_bunch
$this->doctrine->em->persist($property);
$persist_count++;
// If the number of properties ready to be flushed is the number set in $flush_count, lets flush these properties
if ($persist_count == $flush_count) {
$this->doctrine->em->flush();
$this->doctrine->em->clear();
$this->doctrine->mssql->clear();
}
}
// Flush any remaining properties
$this->doctrine->em->flush();
$i += $flush_count;
}
}
Obviously this is wrong, but I haven't been able to find anywhere to show me a proper example. At the moment it just runs out of memory for some reason and complains about duplicates in the pivot table. How do I get a proper relationship set up so I don't reference the pivot table and can instead directly add FeatureOptions to a Property?
Ok, managed to get it working by changing in Property this:
/**
* #ORM\ManyToMany(targetEntity="FeaturesOption", mappedBy="properties")
*/
protected $featuresOptions;
to this:
/**
* #ORM\ManyToMany(targetEntity="FeaturesOption")
* #ORM\JoinTable(name="properties_features",
* joinColumns={#ORM\JoinColumn(name="property_id", referencedColumnName="legacy_id")},
* inverseJoinColumns={#ORM\JoinColumn(name="feature_id", referencedColumnName="id")}
* )
*/
protected $featuresOptions;
Dropping the pivot table entity, and dropping the inverse reference stuff in the FeaturesOption entity.
i explain my problem, asking sorry for my english!
I have 2 entity: Projects and Operations. Each projects can have more operations, each operation can have different price.
So, i have created a new entity ProgettoOperazionePrezzo
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var float
*
* #ORM\Column(name="prezzo", type="decimal")
*/
private $prezzo;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set prezzo
*
* #param float $prezzo
* #return ProgettoOperazionePrezzo
*/
public function setPrezzo($prezzo)
{
$this->prezzo = $prezzo;
return $this;
}
/**
* Get prezzo
*
* #return float
*/
public function getPrezzo()
{
return $this->prezzo;
}
/**
* #ORM\ManyToOne(targetEntity="Progetto")
* #ORM\JoinColumn(name="progetto_id", referencedColumnName="id")
**/
private $progetto;
/**
* Set progetto
*
* #param \Management\ProgettiBundle\Entity\Progetto $progetto
* #return ProgettoOperazionePrezzo
*/
public function setProgetto(\Management\ProgettiBundle\Entity\Progetto $progetto = null)
{
$this->progetto = $progetto;
return $this;
}
/**
* Get progetto
*
* #return \Management\ProgettiBundle\Entity\Progetto
*/
public function getProgetto()
{
return $this->progetto;
}
/**
* #ORM\ManyToOne(targetEntity="Operazione")
* #ORM\JoinColumn(name="operazione_id", referencedColumnName="id")
**/
private $operazione;
/**
* Set operazione
*
* #param \Management\ProgettiBundle\Entity\Operazione $operazione
* #return ProgettoOperazionePrezzo
*/
public function setOperazione(\Management\ProgettiBundle\Entity\Operazione $operazione = null)
{
$this->operazione = $operazione;
return $this;
}
/**
* Get operazione
*
* #return \Management\ProgettiBundle\Entity\Operazione
*/
public function getOperazione()
{
return $this->operazione;
}
Now i want create a form to save in database all the operations that i chose with checkbutton.
$operazione = new ProgettoOperazionePrezzo();
$progetto = $this->getDoctrine()->getRepository('ManagementProgettiBundle:ProgettoOperazionePrezzo')->find($id_progetto);
$form = $this->createFormBuilder($operazione)
->add('operazione','entity',array(
'label'=>'Operazioni da effettuare:',
'multiple'=>true,
'expanded'=>true,
'class'=>'ManagementProgettiBundle:Operazione',
'property'=>'nome',
'query_builder' => function(EntityRepository $er)
{
return $er->createQueryBuilder('u')
->orderBy('u.nome', 'ASC');
}))
->add('Passo successivo','submit');
$form->handleRequest($request);
if($form->isValid()){
$em = $this->getDoctrine()->getManager();
$operazione->setProgetto($progetto);
$em->persist($operazione);
$em->flush();
//return $this->redirect($this->generateUrl('management_progetti_nuovo_progetto_p3',array('id_progetto'=>$id_progetto)));
}
I have no problem to show the form...but it dwsnt works when i try to save in database my choices cause it give me this error:
Catchable Fatal Error: Argument 1 passed to Management\ProgettiBundle\Entity\ProgettoOperazionePrezzo::setOperazione() must be an instance of Management\ProgettiBundle\Entity\Operazione, instance of Doctrine\Common\Collections\ArrayCollection given, called in D:\xampp\htdocs\alemanno_management\vendor\symfony\symfony\src\Symfony\Component\PropertyAccess\PropertyAccessor.php on line 345 and defined in D:\xampp\htdocs\alemanno_management\src\Management\ProgettiBundle\Entity\ProgettoOperazionePrezzo.php line 108
What am i doing of wrong?!!?maybe all??please...can u tell me how can i resolve this?!
Because you fetch multiple results from database, your $progetto variable will contain an instance of ArrayCollection, over which you should iterate. Because your query contains an id which should be unique, I assume that you want to fetch only one results:
$progetto = $this->getDoctrine()->getRepository('ManagementProgettiBundle:ProgettoOperazionePrezzo')->findOneBy(array('id' => $id_progetto));
Now your $progetto variable should point to an instance of Management\ProgettiBundle\Entity\Operazione.
Try to use next entity, please:
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var float
*
* #ORM\Column(name="prezzo", type="decimal")
*/
private $prezzo;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set prezzo
*
* #param float $prezzo
* #return ProgettoOperazionePrezzo
*/
public function setPrezzo($prezzo)
{
$this->prezzo = $prezzo;
return $this;
}
/**
* Get prezzo
*
* #return float
*/
public function getPrezzo()
{
return $this->prezzo;
}
/**
* #ORM\ManyToOne(targetEntity="Progetto")
* #ORM\JoinColumn(name="progetto_id", referencedColumnName="id")
**/
private $progetto;
/**
* Set progetto
*
* #param \Management\ProgettiBundle\Entity\Progetto $progetto
* #return ProgettoOperazionePrezzo
*/
public function setProgetto(\Management\ProgettiBundle\Entity\Progetto $progetto = null)
{
$this->progetto = $progetto;
return $this;
}
/**
* Get progetto
*
* #return \Management\ProgettiBundle\Entity\Progetto
*/
public function getProgetto()
{
return $this->progetto;
}
public function __construct() {
$this->operazione = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #ORM\ManyToOne(targetEntity="Operazione")
* #ORM\JoinColumn(name="operazione_id", referencedColumnName="id")
**/
private $operazione;
/**
* Set operazione
*
* #param \Doctrine\Common\Collections\ArrayCollection $operazione
* #return ProgettoOperazionePrezzo
*/
public function setOperazione(\Doctrine\Common\Collections\ArrayCollection $operazione = null)
{
$this->operazione = $operazione;
return $this;
}
/**
* Get operazione
*
* #return \Doctrine\Common\Collections\ArrayCollection
*/
public function getOperazione()
{
return $this->operazione;
}
I have problems with my classes Symfony2.
I have 3 classes "Niveau, Classe and Serie" that here. A class is related to a level and against a Series by Series Level and are in contact with several class. Here is the source code
/**
* KS\SchoolBundle\Entity\Niveau
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="KS\SchoolBundle\Entity\NiveauRepository")
*/
class Niveau
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $niveau
*
* #ORM\Column(name="niveau", type="string", length=255)
*/
private $niveau;
/**
* #var string $code
*
* #ORM\Column(name="code", type="string", length=255)
*/
private $code;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set niveau
*
* #param string $niveau
* #return Niveau
*/
public function setNiveau($niveau)
{
$this->niveau = $niveau;
return $this;
}
/**
* Get niveau
*
* #return string
*/
public function getNiveau()
{
return $this->niveau;
}
/**
* Set code
*
* #param string $code
* #return Niveau
*/
public function setCode($code)
{
$this->code = $code;
return $this;
}
/**
* Get code
*
* #return string
*/
public function getCode()
{
return $this->code;
}
}
/**
* KS\SchoolBundle\Entity\Serie
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="KS\SchoolBundle\Entity\SerieRepository")
*/
class Serie
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $serie
*
* #ORM\Column(name="serie", type="string", length=255)
*/
private $serie;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $serie
* #return Serie
*/
public function setSerie($serie)
{
$this->serie = $serie;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getSerie()
{
return $this->seriee;
}
}
/**
* KS\SchoolBundle\Entity\Classe
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="KS\SchoolBundle\Entity\ClasseRepository")
*/
class Classe
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
*
* #var type integer
*
* #ORM\ManyToOne(targetEntity="KS\SchoolBundle\Entity\Niveau")
* #ORM\JoinColumn(nullable=false)
*/
private $niveau;
/**
*
* #var type integer
*
* #ORM\ManyToOne(targetEntity="KS\SchoolBundle\Entity\Serie")
* #ORM\JoinColumn
*/
private $serie;
/**
*
* #var type string
*
* #ORM\ManyToOne(targetEntity="KS\SchoolBundle\Entity\Section", inversedBy="classes")
* #ORM\JoinColumn(nullable=false)
*/
private $section;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set niveau
*
* #param KS\School\Entity\Niveau $niveau
* #return Classe
*/
public function setNiveau(\KS\School\Entity\Niveau $niveau)
{
$this->niveau = $niveau;
return $this;
}
/**
* Get niveau
*
* #return KS\School\Entity\Niveau
*/
public function getNiveau()
{
return $this->niveau;
}
/**
* Set serie
*
* #param KS\School\Entity\Serie $serie
* #return Classe
*/
public function setSerie(\KS\School\Entity\Serie $serie)
{
$this->serie = $serie;
return $this;
}
/**
* Get serie
*
* #return KS\School\Entity\Serie
*/
public function getSerie()
{
return $this->serie;
}
/**
* Set section
*
* #param KS\School\Entity\Section $section
* #return Classe
*/
public function setSection(\KS\School\Entity\Section $section)
{
$this->section = $section;
return $this;
}
/**
* Get section
*
* #return KS\School\Entity\Section
*/
public function getSection()
{
return $this->section;
}
public function __toString() {
return $this->getNiveau() . ' ' . $this->getSerie();
}
}
My problem is that entity in a field I want to display a dropdown that has value as a concatenation of the code level and series of Series I which procedé as follows
->add('class', 'entity', array(
'class' => 'KSSchoolBundle:Classe',
'property' => 'value',
'query_builder' => function (\KS\SchoolBundle\Entity\ClasseRepository $er) {
$results = $er->findAllClassesByCodeAndSerie();
$data = array();
foreach ($results as $result) {
$data[] = array(
'id' => $result['id'],
'value' => $result['code'] . ' ' . is_null($result['serie']) ? '' : $result['serie'],
);
}
return $data;
},
)
)
but nothing since there. query_builder return $data that is as you see an array. id must be the value of the option tag value and value should be what the user must see, but I do not see how to do this. The browser give this error Expected argument of type "Doctrine\ORM\QueryBuilder", "array" given
I wonder if that would be a way to do it right the Class class at the __toString () whereby it returns something like getNiveau (). getCode (). ''. getSerie (). getSerie ()
Please one hand it's been two days that I am on this form.
You return an array instead of a QueryBuilder instance in your options array for the entity field type named 'class'.
The wrong part is this one:
'query_builder' => function (\KS\SchoolBundle\Entity\ClasseRepository $er) {
// this is wrong as it does not return a Query but your Class entities themself ...
// findByCodeAndSerie would normally receive 2 arguments: $code & $serie
// but anyway ... this does not belong here !
$results = $er->findAllClassesByCodeAndSerie();
// ... weird stuff
$data = array();
// ... more weird stuff
return $data; /// you return an array instead of QueryBuilder
a correct implementation would be something like this:
use KS\SchoolBundle\Entity\ClasseRepository;
// ...
// 'property' => 'value', // remove this !!
'query_builder' => function(ClasseRepository $er) {
return $er->createQueryBuilder('c')
->orderBy('c.code', 'ASC');
},
now just add the __toString() method to your Class entity. This will be the rendered label for the entity:
public function __toString()
{
return $this->niveau . $this->code . ' ' . $this->serie . $this->serie;
}
Read the enitity field type reference for more information and examples.