how to sort a multiple select field in symfony2 - php

I have a table question, the field "valeurs default" has the answers to all the questions which's gonna be a multiple selection field my problem is to add (Action box) a small button to order the answers for example for the question: "age"--> the answers will be displayed after clicking on the order button: " 20->25 25->30 30->35 "
this is how it appears in my template
can you help me please?
this is my entity "Question"
class Question
{/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="Libelle", type="string", length=150)
*/
private $libelle;
/**
* #var string
*
* #ORM\Column(name="TypeQuestion", type="string", length=150)
*/
protected $TypeQuestion;
/**
* #ORM\ManyToMany(targetEntity="tuto\BackofficeBundle\Entity\Service")
*/
protected $Service;
/**
* #ORM\ManyToMany(targetEntity="tuto\BackofficeBundle\Entity\ValeursDefault")
*/
protected $ValeursDefault;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set libelle
*
* #param string $libelle
*
* #return Question
*/
public function setLibelle($libelle)
{
$this->libelle = $libelle;
return $this;
}
/**
* Get libelle
*
* #return string
*/
public function getLibelle()
{
return $this->libelle;
}
/**
* Constructor
*/
public function __construct()
{
$this->Service = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add Service
*
* #param \tuto\BackofficeBundle\Entity\Service $service
* #return Question
*/
public function addService(\tuto\BackofficeBundle\Entity\Service $service)
{
$this->Service[] = $service;
return $this;
}
/**
* Remove Service
*
* #param \tuto\BackofficeBundle\Entity\Service $service
*/
public function removeService(\tuto\BackofficeBundle\Entity\Service $service)
{
$this->Service->removeElement($service);
}
/**
* Get Service
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getService()
{
return $this->Service;
}
/**
* Add ValeursDefault
*
* #param \tuto\BackofficeBundle\Entity\ValeursDefault $valeursDefault
* #return Question
*/
public function addValeursDefault(\tuto\BackofficeBundle\Entity\ValeursDefault $valeursDefault)
{
$this->ValeursDefault[] = $valeursDefault;
return $this;
}
/**
* Remove ValeursDefault
*
* #param \tuto\BackofficeBundle\Entity\ValeursDefault $valeursDefault
*/
public function removeValeursDefault(\tuto\BackofficeBundle\Entity\ValeursDefault $valeursDefault)
{
$this->ValeursDefault->removeElement($valeursDefault);
}
/**
* Get ValeursDefault
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getValeursDefault()
{
return $this->ValeursDefault;
}
/**
* Set TypeQuestion
*
* #param string $typeQuestion
* #return Question
*/
public function setTypeQuestion($typeQuestion)
{
$this->TypeQuestion = $typeQuestion;
return $this;
}
/**
* Get TypeQuestion
*
* #return string
*/
public function getTypeQuestion()
{
return $this->TypeQuestion;
}
}
the html.twig file

Write a twig extension that sorts ValeursDefault in twig.It's usually what I do with nested objects.
for more details http://symfony.com/doc/current/cookbook/templating/twig_extension.html
I had a similar problem before wanting to order child objects of an entity based on an attribute called position, so I wrote something like this
public function orderPosition($arr) {
$size = count($arr);
for ($i = 0; $i < $size; $i++) {
for ($j = 0; $j < $size - 1 - $i; $j++) {
if ($arr[$j + 1]->getPosition() < $arr[$j]->getPosition()) {
$this->swap($arr, $j, $j + 1);
}
}
}
return $arr;
}
For your case, instead of getPosition() you'd be using whatever function you have in ValeursDefault that you want to sort by

I think you can sort your values using Doctrine :
http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/tutorials/ordered-associations.html
/**
* #ORM\ManyToMany(targetEntity="tuto\BackofficeBundle\Entity\ValeursDefault")
* #ORM\OrderBy({"value" = "ASC"})
*/
protected $ValeursDefault;

Related

Generating Symfony Form from generic data

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

Symfony3 I have to show from a related entity

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

Doctrine Get the result of a DQL Query in a nested form

I have the following problem:
I have the following method that fetches the GPS points of a vessel:
/**
* #param array $mmsids
* #param unknown $longituteMin
* #param unknown $longtitudeMax
* #param unknown $latitudeMin
* #param unknown $latitudeMax
* #param \Datetime $timeInterval
*
* #throws EmptyParamGivenException
* #throws Exception
*
* #return Vesel[] with their routes
*/
public function getRoutes(array $mmsids=[],
$longituteMin=null,
$longtitudeMax=null,
$latitudeMin=null,
$latitudeMax=null,
\DateTime $fromDate=null,
\DateTime $toDate=null
) {
$em=$this->getEntityManager();
$query=$em->createQueryBuilder('v')
->from('AppBundle:Vesel', 'v')
->innerJoin('v.veselMoveStatuses','m')
->select('v.mmsi,m.logtitude,m.latitude,m.timestamp')
->addOrderBy('v.mmsi','ASC')
->addOrderBy('m.timestamp','DESC');
if(!empty($longituteMin)){
$query->andWhere('m.logtitude >= :long_min')->setParameter(':long_min',$longituteMin);
}
if(!empty($longtitudeMax)) {
$query->andWhere('m.logtitude <= :long_max')->setParameter(':long_max',$longituteMax);
}
if(!empty($latitudeMin)){
$query->andWhere('m.latitude >= :lat_min')->setParameter(':lat_min',$latitudeMin);
}
if(!empty($latitudeMax)){
$query->andWhere('m.latitude <= :lat_max')->setParameter(':lat_max',$latitudeMin);
}
if(!empty($mmsids)){
$query->andWhere('v.mmsi IN (:mmsids)')->setParameter('mmsids', $mmsids,\Doctrine\DBAL\Connection::PARAM_STR_ARRAY);
}
$paramsToValidate=[RouteInputParameter::PARAM_DATE_FROM=>$fromDate,RouteInputParameter::PARAM_DATE_TO=>$toDate];
if($fromDate!==null && $toDate!==null){
InputValidator::dateRangeValidation($paramsToValidate,RouteInputParameter::PARAM_DATE_FROM,RouteInputParameter::PARAM_DATE_TO);
$query->andWhere('m.timestamp BETWEEN :date_min AND :date_max')
->setParameters(['date_min'=>$fromDate,'date_max'=>$toDate]);
} else if($fromDate!==null) {
$query->andWhere('m.timestamp <= :date_min')
->setParameters(['date_min'=>$fromDate]);
} else if($toDate!==null) {
$query->where('m.timestamp >= :date_max')
->setParameters(['date_max'=>$toDate]);
}
$query = $query->getQuery();
return $query->getResult();
}
What I want to achieve it that I want to generate the result in a nested way like that:
[
[
"mmsi"=>"^somevalue^"
points=>[
"longtitude":"^longtitude_value^",
"latitude":"^latitude_value^",
"time":"^time_value^"
],
....
],
....
]
do you have any idea if there is an internal Doctrine mechanism that allows me to do this or should I implement my own?
The Vessel Entity is:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="vessel",indexes={
* #ORM\Index(name="mmsi",columns={"mmsi"})
* })
*/
class Vesel
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #var integer
*/
private $id;
/**
* #ORM\Column(type="integer",name="mmsi")
* #var integer
*/
private $mmsi;
/**
* #ORM\OneToMany(targetEntity="VesselMoveStatus",mappedBy="vesel")
* #var \Doctrine\Common\Collections\Collection
*/
private $veselMoveStatuses;
/**
* Constructor
*/
public function __construct($mmsi)
{
$this->veselMoveStatuses = new \Doctrine\Common\Collections\ArrayCollection();
$this->setMmsi($mmsi);
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set mmsi
*
* #param integer $mmsi
*
* #return Vesel
*/
public function setMmsi($mmsi)
{
$this->mmsi = $mmsi;
return $this;
}
/**
* Get mmsi
*
* #return integer
*/
public function getMmsi()
{
return $this->mmsi;
}
/**
* Add veselMoveStatus
*
* #param \AppBundle\Entity\VesselMoveStatus $veselMoveStatus
*
* #return Vesel
*/
public function addVeselMoveStatus(\AppBundle\Entity\VesselMoveStatus $veselMoveStatus)
{
$this->veselMoveStatuses[] = $veselMoveStatus;
return $this;
}
/**
* Remove veselMoveStatus
*
* #param \AppBundle\Entity\VesselMoveStatus $veselMoveStatus
*/
public function removeVeselMoveStatus(\AppBundle\Entity\VesselMoveStatus $veselMoveStatus)
{
$this->veselMoveStatuses->removeElement($veselMoveStatus);
}
/**
* Get veselMoveStatuses
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getVeselMoveStatuses()
{
return $this->veselMoveStatuses;
}
}
And is related into VesselMoveStatus entity:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\Vesel;
/**
* #ORM\Entity(repositoryClass="AppBundle\Repository\VeselRouteRepository")
* #ORM\Table(name="vessel_position_status",indexes={
* #ORM\Index(name="position",columns={"long","lat"})
* })
*/
class VesselMoveStatus
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id=null;
/**
* #ORM\ManyToOne(targetEntity="Vesel",inversedBy="veselMoveStatuses")
* #ORM\JoinColumn(name="vesel_id", referencedColumnName="id")
* #var Vesel
*/
private $vesel=null;
/**
* #ORM\Column(name="status",type="integer")
* #var integer|null
*/
private $status=null;
/**
* #ORM\Column(name="speed",type="integer")
* #var integer|null
*/
private $speed=null;
/**
* #ORM\Column(name="long",type="float")
* #var float|null
*/
private $logtitude=null;
/**
* #ORM\Column(name="lat",type="float")
* #var float|null
*/
private $latitude=null;
/**
* #ORM\Column(name="course",type="integer")
* #var integer|null
*/
private $course=null;
/**
* #ORM\Column(name="heading",type="integer")
* #var integer|null
*/
private $heading=null;
/**
* #ORM\Column(name="rotation",type="integer")
* #var integer|null
*/
private $rotation=null;
/**
* #ORM\Column(name="timestamp",type="datetime")
* #var Datetime|null
*/
private $timestamp=null;
public function __construct(
Vesel $vesel=null,
$status=null,
$speed=null,
$long=null,
$lat=null,
$course=null,
$heading=null,
$rotation=null,
$timestamp=null
){
$this->setVesel($vesel)
->setStatus($status)
->setSpeed($speed)
->setLogtitude($long)
->setLatitude($lat)
->setCourse($course)
->setHeading($heading)
->setRotation($rotation)
->setTimestamp($timestamp);
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set mmsi
*
* #param integer $mmsi
*
* #return VesselMoveStatus
*/
public function setMmsi($mmsi)
{
$this->mmsi = $mmsi;
return $this;
}
/**
* Get mmsi
*
* #return integer
*/
public function getMmsi()
{
return $this->mmsi;
}
/**
*
* #param integer $status
* #return \AppBundle\Entity\VesselMoveStatus
*/
public function setStatus($status)
{
$this->status=$status;
return $this;
}
/**
*
* #return \AppBundle\Entity\integer|NULL
*/
public function getStatus()
{
return $this->status;
}
/**
* Set speed
*
* #param integer $speed
*
* #return VesselMoveStatus
*/
public function setSpeed($speed)
{
$this->speed = $speed;
return $this;
}
/**
* Get speed
*
* #return float
*/
public function getSpeed()
{
return $this->speed/10;
}
/**
* Set logtitude
*
* #param integer $logtitude
*
* #return VesselMoveStatus
*/
public function setLogtitude($logtitude)
{
$this->logtitude = $this->sanitizeGpsCoordinate($logtitude);
return $this;
}
/**
* Get logtitude
*
* #return float
*/
public function getLogtitude()
{
return $this->logtitude;
}
/**
* Set latitude
*
* #param integer $latitude
*
* #return VesselMoveStatus
*/
public function setLatitude($latitude)
{
$this->latitude = $this->sanitizeGpsCoordinate($latitude);
return $this;
}
/**
* Get latitude
*
* #return float
*/
public function getLatitude()
{
$latitude=$this->latitude;
return $latitude;
}
/**
* Set course
*
* #param integer $course
*
* #return VesselMoveStatus
*/
public function setCourse($course)
{
$this->course = $course;
return $this;
}
/**
* Get course
*
* #return integer
*/
public function getCourse()
{
return $this->course;
}
/**
* Set heading
*
* #param integer $heading
*
* #return VesselMoveStatus
*/
public function setHeading($heading)
{
$this->heading = $heading;
return $this;
}
/**
* Get heading
*
* #return integer
*/
public function getHeading()
{
return $this->heading;
}
/**
* Set rotation
*
* #param integer $rotation
*
* #return VesselMoveStatus
*/
public function setRotation($rotation)
{
$this->rotation = $rotation;
return $this;
}
/**
* Get rotation
*
* #return integer
*/
public function getRotation()
{
return $this->rotation;
}
/**
* Set timesptamp
*
* #param string $timesptamp
*
* #return VesselMoveStatus
*/
public function setTimestamp($timesptamp)
{
$this->timestamp = date_create_from_format("Y-m-d H:i:s.u",$timesptamp);
return $this;
}
/**
* Get timesptamp
*
* #return \DateTime
*/
public function getTimestamp()
{
return $this->timestamp;
}
/**
* Set vesel
*
* #param \AppBundle\Entity\Vesel $vesel
*
* #return VesselMoveStatus
*/
public function setVesel(\AppBundle\Entity\Vesel $vesel = null)
{
$this->vesel = $vesel;
return $this;
}
/**
* Get vesel
*
* #return \AppBundle\Entity\Vesel
*/
public function getVesel()
{
return $this->vesel;
}
/**
* Sometimes a GPS Coordinate may have the following format:
* 1,234532 if inserted as is then itn WONT be retreived correctly.
* Please use this method to sanitize the gps coordinate on setter method.
*
* #param string | float $coordinate
* #return number
*/
private function sanitizeGpsCoordinate($coordinate)
{
if(is_string($coordinate))
{
$coordinate=str_replace(',','.',$coordinate);
}
return (float)$coordinate;
}
}
The way you want to transform the data is not standard thus there is nothing generic in Doctrine to do so. But it's still very simple to achieve the objective you want.
However, IMHO the simplest solution is to use a closure to transform the result:
$result = $query->getResult();
$formatter = function($row) {
return [
"mmsi" => $row['mmsi']
"points" => [
"longtitude" => $row['logtitude'],
"latitude" => $row['latitude'],
"time" => $row['timestamp']
]
];
};
return array_map($formatter, $result);
The final array will have one element per point (veselMoveStatuses). If what you actually want is to have one element per vesel, consider changing the SELECT and adapt the formatter accordingly.
->select('v,m')
The result will be an array of Vesel objects with the veselMoveStatuses association already loaded (see this doc - section "Retrieve a CmsUser and fetch join all the phonenumbers he has").

Save copy of entity doctrine/symfony2

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();
// .....
}

Setting up a manytomany relationship in Doctrine

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.

Categories