SF3+Doctrine calculate price between dates - php

So in my Symfony 3 project I need to create a sort of price calculator with takes 3 params: date_from, date_to, guest_number. Table in MySql looks like:
-----------------------------------------------------------------
id | date_from | date_to | people | price
-----------------------------------------------------------------
1 | 2016-01-15 | 2016-04-20 | 1 | 100
-----------------------------------------------------------------
2 | 2016-04-20 | 2016-08-15 | 1 | 200
-----------------------------------------------------------------
3 | 2016-04-20 | 2016-08-15 | 2 | 250
For example, someone choose 2016-01-01 till 2016-01-10 for 1 guest. Calculator should return 1000. And it is no big deal to create SQL statement for this
Example 2, someone choose 2016-04-15 til 2016-04-25 for 1 person.
The question is how can I build with Doctrine QueryBuilder statement which would calculate 'n' days from one period multiply price and 'n' days from another period multiply corresponding price?

Let's say you have an entity Calendar:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="CalendarRepository")
* #ORM\Table(name="calendar")
*/
class Calendar
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="date")
*/
private $dateFrom;
/**
* #ORM\Column(type="date")
*/
private $dateTo;
/**
* #ORM\Column(type="integer")
*/
private $people;
/**
* #ORM\Column(type="integer")
*/
private $price;
}
Then your repository class could look like this:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\EntityRepository;
class CalendarRepository extends EntityRepository
{
public function findPriceFor(\DateTime $dateFrom, \DateTime $dateTo, $nrOfPeople)
{
$qb = $this->createQueryBuilder('calendar');
$qb->select('SUM(
CASE
WHEN calendar.dateFrom >= :dateFromChosen AND calendar.dateTo >= :dateToChosen THEN DATE_DIFF(:dateToChosen, calendar.dateFrom)
WHEN calendar.dateFrom <= :dateFromChosen AND calendar.dateTo >= :dateToChosen THEN DATE_DIFF(:dateToChosen, :dateFromChosen)
WHEN calendar.dateFrom <= :dateFromChosen AND calendar.dateTo <= :dateToChosen THEN DATE_DIFF(calendar.dateTo, :dateFromChosen)
WHEN calendar.dateFrom >= :dateFromChosen AND calendar.dateTo <= :dateToChosen THEN DATE_DIFF(calendar.dateTo, calendar.dateFrom)
ELSE 0
END
)*calendar.price AS intervalPrice');
$qb->andWhere('calendar.people = :nrOfPeople')
->andWhere(
$qb->expr()->andX(
$qb->expr()->lt('calendar.dateFrom', ':dateToChosen'),
$qb->expr()->gt('calendar.dateTo', ':dateFromChosen')
)
);
$qb->setParameter('nrOfPeople', $nrOfPeople)
->setParameter('dateFromChosen', $dateFrom->format('Y-m-d'))
->setParameter('dateToChosen', $dateTo->format('Y-m-d'));
$qb->groupBy('calendar.id');
$query = $qb->getQuery();
$resultArray = $query->execute();
$totalPrice = array_sum(array_column($resultArray, 'intervalPrice'));
return $totalPrice;
}
}
If we took your example MySQL table, and decide to calculate a price for 1 person, from "2016-04-15" to "2016-04-25", then result would be this:

Related

How to map one-to-one relation without join column (entities are joined via their IDs)?

In my work, I am trying to map the legacy database scheme with Doctrine. I can't change this scheme, because it is used by other company applications. Here is a brief scheme overview:
Table - global_register_item
ID | NAME | DTYPE
1 | "global register item with article #1" | law_regulation
2 | "global register item without article #1" | financial_reporter
3 | "global register item without article #2" | law_regulation
4 | "global register item without article #3" | law_regulation
5 | "global register item with article #2" | financial_reporter
Table - article
ID | SID | other fields which I actually do not need
1 | 89 | ...
5 | 45 | ...
Table - law_regulation
ID | other fields
1 | ...
3 | ...
4 | ...
Table - financial_reporter
ID | other fields
2 | ...
5 | ...
So global_register_item is a parent and law_regulation and financial_reporter inherit from this table. To solve this I used class table inheritance and it works fine.
The problem is a relation between global_register_item and article. It is one-to-one relation and joining is done via their ID columns (if there is a record in global_register_item with relation to article, there is a record in article table with the same ID). But some records in global_register_item doesn't have record in article. Is there any way how to map this relation with Doctrine?
EDIT 1
Here is my PHP code from the project. Btw. I only need to read records. And I need to get information about SID column to my GlobalRegisterItem entity.
Class GlobalRegisterItem
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="global_register_item")
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="DTYPE", type="string")
* #ORM\DiscriminatorMap({
* "law_regulation" = "App\Entity\LawRegulation",
* "financial_reporter" = "App\Entity\FinancialReporter"})
*/
abstract class GlobalRegisterItem
{
/**
* #var int
* #ORM\Column(name="id", type="integer")
* #ORM\Id
*/
private $id;
/**
* #var string
* #ORM\Column(name="name", type="string")
*/
private $name;
/**
* Article|null
* HOW TO MAP THIS?
*/
private $article;
}
Class Article
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="article")
*/
class Article
{
/**
* #var int
* #ORM\Column(name="id", type="integer")
* #ORM\Id
*/
private $id;
/**
* #var int
* #ORM\Column(name="SID", type="int")
*/
private $sid;
}
Class LawRegulation
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="law_regulation")
*/
class LawRegulation extends GlobalRegisterItem
{
/** SOME MAPPED FIELDS */
}
Class FinancialReporter
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="law_regulation")
*/
class FinancialReporter extends GlobalRegisterItem
{
/** SOME MAPPED FIELDS */
}
You can use a OneToOne bidirectional relation, in the Article entity:
/**
* #ORM\OneToOne(targetEntity="GlobalRegisterItem", inversedBy="article")
* #ORM\JoinColumn(name="id", referencedColumnName="id", nullable=true)
*/
private $item;
And reference it in your GlobalRegisterItem class:
/**
* Article|null
* #ORM\OneToOne(targetEntity="Article", mappedBy="item")
*/
private $article;
/**
* Gets the sid of the article (if any).
* #returns int|null
*/
public function getArticleSid()
{
if (null !== $this->article) {
return $this->article->getSid();
}
return null;
}
One possible approach how to solve this (if you just need to read data) is:
Create view from global_register_item and article
SELECT global_register_item.*, article.SID AS `SID`
FROM global_register_item
LEFT JOIN article ON global_register_item.id = article.id
ID | NAME | DTYPE | SID
1 | "global register item with article #1" | law_regulation | 89
2 | "global register item without article #1" | financial_reporter | NULL
3 | "global register item without article #2" | law_regulation | NULL
4 | "global register item without article #3" | law_regulation | NULL
5 | "global register item with article #2" | financial_reporter | 45
Class GlobalRegisterItem
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="global_register_item_view")
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="DTYPE", type="string")
* #ORM\DiscriminatorMap({
* "law_regulation" = "App\Entity\LawRegulation",
* "financial_reporter" = "App\Entity\FinancialReporter"})
*/
abstract class GlobalRegisterItem
{
/**
* #var int
* #ORM\Column(name="id", type="integer")
* #ORM\Id
*/
private $id;
/**
* #var string
* #ORM\Column(name="name", type="string")
*/
private $name;
/**
* int|null
* #ORM\Column(name="SID", type="integer")
*/
private $sid;
}
I think this is far from being optimal, but this is the best solution I could come up with.

Doctrine 2 - Error Persisting Subclass of Class Table Inheritance Mapping Strategy

I've implement Class Table Inheritance using Doctrine 2 in my Symfony 3 project, so as to have one base profile table, that houses both employee and company profiles.
When trying to persist a sub class (EmployeeProfile) of the mapped super class (AbstractProfile), I get the following error:
An exception occurred while executing 'INSERT INTO profile (id) VALUES
(?)' with params [27, 10, 85, \"employee\"]:\n\nSQLSTATE[HY093]:
Invalid parameter number: number of bound variables does not match
number of tokens
I'm not entirely sure what's going wrong, and why Doctrine is generating a query that's entirely ignoring the AbstractProfile's properties. Initially I thought it was due to said properties not being visible to the children, but even after setting the properties to protected, the error remains.
How exactly can I fix this, or am I trying to fit a square peg into a round hole by not using this functionality for what is was intended?
profile DB Table:
+------------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | NO | | NULL | |
| type | varchar(100) | NO | | NULL | |
| status | int(11) | NO | | NULL | |
| created_at | datetime | NO | | CURRENT_TIMESTAMP | |
| updated_at | datetime | NO | | CURRENT_TIMESTAMP | |
+------------+--------------+------+-----+-------------------+----------------+
AbstractProfile Super Class:
/**
* AbstractProfile
*
* #ORM\Table(name="profile")
* #ORM\Entity(repositoryClass="ProfileBundle\Repository\ProfileRepository")
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="type", type="string")
* #ORM\DiscriminatorMap({
* "employee" = "EmployeeProfile",
* "company" = "CompanyProfile"
* })
*/
abstract class AbstractProfile
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var int
*
* #ORM\Column(name="status", type="integer")
*/
protected $status;
/**
* #ORM\OneToOne(targetEntity="User", inversedBy="profile")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
//... Getters, setters and all the rest
}
EmployeeProfile Sub Entity:
<?php
/**
* EmployeeProfile
*
* #ORM\Table(name="profile")
* #ORM\Entity
*/
class EmployeeProfile extends AbstractProfile
{
/**
* #var ArrayCollection
*
* #ORM\ManyToMany(targetEntity="Skill", inversedBy="profiles")
* #ORM\JoinTable(name="profile_skills",
* joinColumns={#ORM\JoinColumn(name="profile_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="skill_id", referencedColumnName="id", unique=true)}
* )
*/
private $skills;
public function __construct()
{
$this->skills = new ArrayCollection();
}
//... Getters, setters and all the rest
}
CompanyProfile Sub Entity:
<?php
/**
* CompanyProfile
*
* #ORM\Table(name="profile")
* #ORM\Entity
*/
class CompanyProfile extends AbstractProfile
{
/**
* #var ArrayCollection
*
* #ORM\ManyToMany(targetEntity="Event", inversedBy="profiles")
* #ORM\JoinTable(name="profile_events",
* joinColumns={#ORM\JoinColumn(name="profile_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="event_id", referencedColumnName="id", unique=true)}
* )
*/
private $events;
public function __construct()
{
$this->events = new ArrayCollection();
}
//... Getters, setters and all the rest
}
It looks like you are trying to use #ORM\InheritanceType("JOINED") with a single table. You use #ORM\Table(name="profile") in your 3 entities.
The result is that Doctrine don't know what to do with your entities.
You could try replacing #ORM\InheritanceType("JOINED") by #ORM\InheritanceType("SINGLE_TABLE").

symfony 3 doctrine one to one uni-direction returning unwanted fields when querying

I have got two classes which are being associated using one to one uni-direction
{
id: 1,
name: "onetooneuniparent name",
onetooneunichild: {
id: 1,
name: "onetooneunichild name",
__initializer__: null,
__cloner__: null,
__isInitialized__: true
}
}
the above is the result when I do query like following
http://localhost:8000/onetooneRead?id=1
I want to know where and why the following come from
__initializer__: null,
__cloner__: null,
__isInitialized__: true
my expected result is just this
{
id: 1,
name: "onetooneuniparent name",
onetooneunichild: {
id: 1,
name: "onetooneunichild name"
}
}
OnetoOneUniParent.php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="onetooneuniparent")
*/
class OnetoOneUniParent{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string",name="name")
*/
private $name;
/**
* #ORM\OneToOne(targetEntity="OnetoOneUniChild",cascade={"persist"})
* #ORM\JoinColumn(name="child_id", referencedColumnName="id")
*/
private $onetooneunichild;
<.... getter and setter here ...>
}
OnetoOneUniChild.php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="onetooneunichild")
*/
class OnetoOneUniChild{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string",name="name")
*/
private $name;
<.... getter and setter here ...>
This is the method in controller
/**
* #Route("/onetooneRead")
* #Method("GET")
*/
public function onetooneReadAction(Request $request){
$logger = $this->get('logger');
$encoders = array(new XmlEncoder(), new JsonEncoder());
$normalizers = array(new ObjectNormalizer());
$serializer = new Serializer($normalizers, $encoders);
$logger->info('onetoone Read');
$id = $request->query->get("id");
$em = $this->getDoctrine()->getManager();
$onetooneuniparent = $em->getRepository('AppBundle:OnetoOneUniParent')->find($id);
$onetooneuniparentJson = $serializer->serialize($onetooneuniparent, 'json');
$response = new JsonResponse();
$response->setContent($onetooneuniparentJson);
return $response;
}
This is what is inside in MySQL
mysql> select * from onetooneuniparent;
+----+----------+------------------------+
| id | child_id | name |
+----+----------+------------------------+
| 1 | 1 | onetooneuniparent name |
| 2 | 2 | onetooneuniparent name |
| 3 | 3 | onetooneuniparent name |
+----+----------+------------------------+
3 rows in set (0.00 sec)
mysql> select * from onetooneunichild;
+----+-----------------------+
| id | name |
+----+-----------------------+
| 1 | onetooneunichild name |
| 2 | onetooneunichild name |
| 3 | onetooneunichild name |
+----+-----------------------+
3 rows in set (0.00 sec)
Those functions are part of the Doctrine proxy coding, since you are using Lazy Loading Doctrine needs to keep track of the child entity if it needs to be loaded or not. Part of that keeping track is these functions (I believe it is in this portion of Doctrine)
There may be a way around this which would be to avoid using lazy loading. To do that you can utilize EAGER loading if you always want the child to load with the parent. Alternatively if you only want to use EAGER for this one query and not every time you would have to switch to DQL as documented here or you could use the JOIN comma (second example down) here

Doctrine2 default timestamp wtih "0000-00-00 00:00:00" format?

I am using Doctrine2 ORM. I have an order table.
Name | Type | Attributes | Null | Default
--------------------------------------------------------------------------------
order_id | int | | No | None
date_created | timestamp | | No | CURRENT_TIMESTAMP
date_edited | timestamp | on update CURRENT_TIMESTAMP | No | CURRENT_TIMESTAMP
date_sent | timestamp | | No | 0000-00-00 00:00:00
date_cancelled | timestamp | | No | 0000-00-00 00:00:00
requested_ship_date | timestamp | | No | 0000-00-00 00:00:00
I have added the Timestampable Doctrine Extension to use for the date_created and date_edited fields like so:
/**
* #var \DateTime
*
* #Gedmo\Timestampable(on="create")
* #ORM\Column(type="datetime")
*/
private $date_created;
/**
* #var \DateTime
*
* #Gedmo\Timestampable(on="update")
* #ORM\Column(type="datetime")
*/
private $date_edited;
However, I'm not sure what to do for date_sent and date_cancelled. I want them both to default to 0000-00-00 00:00:00 instead of the current time. I saw this workaround for using timestamps in Doctrine2 without a plugin, but I don't want the default to be the current timestamp for these. The reason being, users can 'save' an order but not 'send' it to someone. Also, I obviously don't want the date_cancelled to be the current timestamp.
Note: I don't want to store nulls in the database, so please don't suggest that.
Thanks in advance.
Update
I currently have this for the three remaining fields in my Order entity.
/**
* #var \DateTime
*
* #ORM\Column(type="datetime", options={"default":"0000-00-00 00:00:00"})
* #ORM\Version
*/
private $date_sent;
/**
* #var \DateTime
*
* #ORM\Column(type="datetime", options={"default":"0000-00-00 00:00:00"})
* #ORM\Version
*/
private $date_cancelled;
/**
* #var \DateTime
*
* #ORM\Column(type="datetime", options={"default":"0000-00-00 00:00:00"})
* #ORM\Version
*/
private $requested_ship_date;
For some reason, when I try to update the requested_ship_date field, it ends up being "0000-00-00 00:00:00". I leave the date_sent and date_cancelled fields null and they update to my local time, not UTC time. However, the date_created and date_edited fields will be updated to the current time in UTC time (how I want it).
Basically, when I'm saving an order it looks like the first row, but I want it to look like the second row (assuming the user requested a ship date of 2015-06-08).
order_id | date_created | date_edited | date_sent | date_cancelled | requested_ship_date
-----------------------------------------------------------------------------------------------------------------------
1 | 2015-06-05 12:00:00 | 2015-06-05 12:00:00 | 2015-06-05 07:00:00 | 2015-06-05 07:00:00 | 0000-00-00 00:00:00
1 | 2015-06-05 12:00:00 | 2015-06-05 12:00:00 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 | 2015-06-08 00:00:00
I have set the timezone in my index.php file like so date_default_timezone_set('Zulu');. I don't reset the timezone anywhere else.
Okay, I found a crazy workaround for this, but I honestly couldn't find a better solution. So, for anyone else stuck in the same mess I am, you're welcome lol.
First, the rules:
date_created = updated only on creation
date_edited = updated on every update
date_sent = updated when user clicks "submit" instead of "save"
date_cancelled = updated when user decides to cancel the order
requested_ship_date = required when creating a new order, this is the date the customer wants the order to be shipped by.
Some code from my Order entity.
/**
* #var \DateTime
*
* #ORM\Column(type="datetime")
* #Gedmo\Timestampable(on="create")
*/
private $date_created;
/**
* #var \DateTime
*
* #ORM\Column(type="datetime")
* #Gedmo\Timestampable(on="update")
*/
private $date_edited;
/**
* #var \DateTime
*
* #ORM\Column(type="datetime", options={"default":"0000-00-00 00:00:00"})
*/
private $date_sent;
/**
* #var \DateTime
*
* #ORM\Column(type="datetime", options={"default":"0000-00-00 00:00:00"})
*/
private $date_cancelled;
/**
* #var \DateTime
*
* #ORM\Column(type="datetime")
* #Gedmo\Timestampable(on="change", field="requested_ship_date")
*/
private $requested_ship_date;
/*
* Constructor
*/
public function __construct()
{
if (!$this->date_sent) $this->date_sent = new DateTime("0000-00-00 00:00:00", new DateTimeZone("Zulu"));
if (!$this->date_cancelled) $this->date_cancelled = new DateTime("0000-00-00 00:00:00", new DateTimeZone("Zulu"));
}
/**
* Updates time sent
*
* #return Order
*/
public function send()
{
$this->date_sent = new DateTime("now");
return $this;
}
/**
* Updates time cancelled
*
* #return Order
*/
public function cancel()
{
$this->date_cancelled = new DateTime("now");
return $this;
}
Explanation:
I did not change anything of how I set up my database columns in my order table. I tried using the #Gedmo\Timestampable plugin for my date_sent and date_cancelled fields, but couldn't get it to work. I noticed that the timezones were off, for some weird reason, so I manually set them in the constructor. It is important to not automatically set it, or you will override values previously set. For some reason unknown to me, I couldn't get the requested_ship_date field working without using the #Gedmo\Timestampable plugin. If I took it out, every set up I tried to use with Doctrines type="datetime" would just result in the column equaling 0000-00-00 00:00:00.
If anybody has any questions, let me know. I had to basically poke at things for awhile until I figured it out. The date_sent and date_cancelled fields worked correctly, and were in the right timezone when I updated them.

How can I add field on the fly in symfony2 entity

I would like to know if exist a way to add fields on the fly to any entity on Symfony2. I'm searching on the big internet and I didn't find anything. When I said "a way", I mean if exist a Doctrine Extension with that behavior, a bundle that implement it, design pattern, etc.
My idea is something similar to Translatable behavior of Doctrine Extensions. Supouse I have a Address entity, so I would like to add some attributes on the fly like street, number, intersections, and others but at the begining I didn't know what fields could exist.
I'm thinking something as 2 entities: Address and AddressFieldValues. Address will have specifics attributes like id, foreing keys of relationships with others classess and will be used to inject the dynamic attributes (a collections of field-values). AddressFieldValue will have the reals fields-values of Address, with the following attributes: id, address_id, field_name, field_value.
So, entity Address could be like this:
/**
* Address
*
* #ORM\Entity(repositoryClass="AddressRepository")
* #ORM\Table(name="address")
*/
class Address
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToMany(
* targetEntity="AddressFieldValues",
* mappedBy="object",
* cascade={"persist", "remove"}
* )
*/
private $field_value;
public function __construct()
{
$this->field_value = new ArrayCollection();
}
public function getFieldValue()
{
return $this->field_value;
}
public function addFieldValue(AddressFieldValues $fv)
{
if (!$this->field_value->contains($fv)) {
$this->field_value[] = $fv;
$fv->setObject($this);
}
}
public function getId()
{
return $this->id;
}
}
and AddressFieldValues entity could be like this:
/**
* #ORM\Entity
* #ORM\Table(name="address_field_values",
* uniqueConstraints={#ORM\UniqueConstraint(name="lookup_unique_idx", columns={
* "object_id", "field"
* })}
* )
*/
class AddressFieldValues
{
/**
* #var integer $id
*
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue
*/
protected $id;
/**
* #var string $field
*
* #ORM\Column(type="string", length=32)
*/
protected $field;
/**
* #ORM\ManyToOne(targetEntity="Address", inversedBy="field_value")
* #ORM\JoinColumn(name="object_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $object;
/**
* #var string $content
*
* #ORM\Column(type="text", nullable=true)
*/
protected $content;
/**
* Convenient constructor
*
* #param string $field
* #param string $value
*/
public function __construct($field, $value)
{
$this->setField($field);
$this->setContent($value);
}
/**
* Get id
*
* #return integer $id
*/
public function getId()
{
return $this->id;
}
/**
* Set field
*
* #param string $field
*/
public function setField($field)
{
$this->field = $field;
return $this;
}
/**
* Get field
*
* #return string $field
*/
public function getField()
{
return $this->field;
}
/**
* Set object related
*
* #param string $object
*/
public function setObject($object)
{
$this->object = $object;
return $this;
}
/**
* Get related object
*
* #return object $object
*/
public function getObject()
{
return $this->object;
}
/**
* Set content
*
* #param string $content
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* Get content
*
* #return string $content
*/
public function getContent()
{
return $this->content;
}
}
So, if I have the following values on table: address_field_values
id | object | field | content
1 | 1 | street | 1st Ave
2 | 1 | number | 12345
3 | 1 | intersections | 2sd Ave and 4th Ave
4 | 2 | street | 1st Ave
5 | 2 | number | 12347
6 | 2 | intersections | 2sd Ave and 4th Ave
7 | 3 | street | 1st Ave
8 | 3 | number | 12349
9 | 3 | intersections | 2sd Ave and 4th Ave
For now address table only have the following values:
| id |
| 1 |
| 2 |
| 3 |
I could like to inject those fields-values to a Address object on the fly, to do something like this:
// if I need get de Address with id = 2
$addressRepository = $em->getRepository('Address');
$address = $addressRepository->find(2);
sprintf('The address is: "%s", #"%s" between "%s".', $address->getStreet(), $address->getNumber(), $address->getIntersections());
// then it should show: The address is 1st Ave, #12347 between 2sd Ave and 4th Ave.
//
// or if I need add a new Address, do something like this:
$address = new Address();
$address->setStreet('1st Ave');
$address->setNumber('12351');
$address->setIntersections('2sd Ave and 4th Ave');
$em->persist($address);
$em->flush();
then it save the address and address_field_values, and the tables have the following values:
// address
| id |
| 1 |
| 2 |
| 3 |
| 4 |
// address_field_values
id | object | field | content
1 | 1 | street | 1st Ave
2 | 1 | number | 12345
3 | 1 | intersections | 2sd Ave and 4th Ave
4 | 2 | street | 1st Ave
5 | 2 | number | 12347
6 | 2 | intersections | 2sd Ave and 4th Ave
7 | 3 | street | 1st Ave
8 | 3 | number | 12349
9 | 3 | intersections | 2sd Ave and 4th Ave
10 | 4 | street | 1st Ave
11 | 4 | number | 12351
12 | 4 | intersections | 2sd Ave and 4th Ave
So, any ideas how can I do that?
Remember, I have as requirement in my bussiness logic that I didn't know what fields could have a Address at beginig so I need to inject the fields on the fly. I use Address as example but this behavior can be used for any entity.
Thanks in advance
I think that your request is similar to a collection in a form (Doctrine2 documentation).
In the documentation, a collection of Tags entities with name property) is linked to a Task entity. In your case, the entity AddressFieldValue will have the field and content properties and the collection of AddressFieldValue entities will be added to Address entity.
So, by using this documentation and replacing Task by Address and Tag by AddressFieldValue it should works.

Categories