OneToMany and ManyToOne relation in Doctrine - strange mapping error - php

I've got two entities mapped like this:
namespace App\Entity\Email;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Contract\Entity\BlameableInterface;
use Knp\DoctrineBehaviors\Contract\Entity\SoftDeletableInterface;
use Knp\DoctrineBehaviors\Contract\Entity\TimestampableInterface;
use Knp\DoctrineBehaviors\Model\Blameable\BlameableTrait;
use Knp\DoctrineBehaviors\Model\SoftDeletable\SoftDeletableTrait;
use Knp\DoctrineBehaviors\Model\Timestampable\TimestampableTrait;
/**
* #ORM\Entity(repositoryClass="App\Repository\Email\EmailRepository")
*/
class Email implements SoftDeletableInterface, TimestampableInterface, BlameableInterface
{
use SoftDeletableTrait;
use TimestampableTrait;
use BlameableTrait;
/**
* #ORM\Column(type="integer")
* #ORM\Id()
* #ORM\GeneratedValue()
*/
private ?int $id = null;
...
/**
* #var Collection|EmailAddress[]
* #ORM\OneToMany(targetEntity="App\Entity\Email\EmailAddress", mappedBy="sentEmail", cascade={"all"}, orphanRemoval=true)
*/
private ?Collection $senders = null;
/***
* #var Collection|EmailAddress[]
* #ORM\OneToMany(targetEntity="App\Entity\Email\EmailAddress", mappedBy="receivedEmail", cascade={"all"}, orphanRemoval=true)
*/
private ?Collection $recipients = null;
...
}
and
namespace App\Entity\Email;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Contract\Entity\BlameableInterface;
use Knp\DoctrineBehaviors\Contract\Entity\SoftDeletableInterface;
use Knp\DoctrineBehaviors\Contract\Entity\TimestampableInterface;
use Knp\DoctrineBehaviors\Model\Blameable\BlameableTrait;
use Knp\DoctrineBehaviors\Model\SoftDeletable\SoftDeletableTrait;
use Knp\DoctrineBehaviors\Model\Timestampable\TimestampableTrait;
/**
* #ORM\Entity()
*/
class EmailAddress implements SoftDeletableInterface, TimestampableInterface, BlameableInterface
{
use SoftDeletableTrait;
use TimestampableTrait;
use BlameableTrait;
/**
* #ORM\Column(type="integer")
* #ORM\Id()
* #ORM\GeneratedValue()
*/
private ?int $id = null;
...
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Email\Email", inversedBy="senders")
* #ORM\JoinColumn()
*/
private ?Email $sentEmail = null;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Email\Email", inversedBy="recipients")
* #ORM\JoinColumn()
*/
private ?Email $receivedEmail = null;
...
}
From unknown reason to me I'm getting message from Doctrine:
The association App\Entity\Email\EmailAddress#receivedEmail refers to the inverse side field App\Entity\Email\Email#recipients which does not exist.
What is wrong with my mapping? I really don't see any error. I've asked my colegues to check my code and they also don't see any problem. Strange thing is that relation sentEmail->senders is mapped according to doctrine right and it's working.
I've also tried to change OneToMany mapping to ManyToMany like this but I've still got same error.
EDIT 1:
Date in database:
Table email
id | created_by_id | updated_by_id | deleted_by_id | deleted_at | created_at | updated_at | subject | content
1 | NULL | NULL | NULL | NULL | 1616156920 | 1616156920 | Test | Test
Table email_address
id | created_by_id | updated_by_id | deleted_by_id | address | deleted_at | created_at | updated_at | sent_email_id | received_email_id
1 | NULL | NULL | NULL | test1#test.com | NULL | 1616156920 | 1616156920 | NULL | 1
2 | NULL | NULL | NULL | test2#test.com | NULL | 1616156920 | 1616156920 | 1 | NULL

This question/answer probably follows under the heading of a 'typo' but I thought it might be interesting to discuss.
The problem is here:
/***
* #var Collection|EmailAddress[]
* #ORM\OneToMany(targetEntity="App\Entity\Email\EmailAddress", mappedBy="receivedEmail", cascade={"all"}, orphanRemoval=true)
*/
private ?Collection $recipients = null;
The extra asterisk /*** in the annotation block opening caused the recipients property to be skipped by Doctrine. But everything still seemed to be okay. The database tables and indexes were all generated as expected.
I made a simple console command to insert an email entity and quickly noticed that the sender address was inserted but not the recipient address. Triple checked the various methods but still no go. Explicitly persisting the address worked but the cascade option should have taken care of that. And of course retrieving the recipient address was not working even after an entity was inserted.
At some point I noticed the /*** and changed it to /** and everything worked as expected. Using a console command to test helped quite a bit as opposed to refreshing a browser and hunting around in the debug bar.
On the plus side, if you ever need to temporarily remove an annotation then just adding an asterisk is basically the same as commenting it out.

Related

Doctrine: can the same attribute make a relation to two different destination attributes?

Is this OneToOne relation possible with Doctrine (in Symfony)?
User Time
+----------+ +-------+
| ... | | ... |
| time_id |o-----+-----o| user |
| | | | ... |
| time2_id |o-----+ | type |
| ... | +-------+
+----------+
That is, a User can potentially have two different Time entities associated to it:
one of type=0 and the other one of type=1.
I could have splitted Time in two different entities, but I thought that this way I
could spare replicating some code, as Time entity has an eventListener and more code associated...
I have coded it like this:
class Time
{
...
/**
* #ORM\OneToOne(targetEntity=User::class, mappedBy="time, cascade={"persist"})
* #ORM\OneToOne(targetEntity=User::class, mappedBy="time2", cascade={"persist"})
*/
private $user;
...}
class User
{
...
/**
* #ORM\OneToOne(targetEntity=Time::class, inversedBy="user", cascade={"persist"})
* #ORM\JoinColumn(name="time_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
*/
private $time;
/**
* #ORM\OneToOne(targetEntity=Time::class, inversedBy="user", cascade={"persist"})
* #ORM\JoinColumn(name="time2_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
*/
private $time2;
...}
And in fact I am flawlessly using it, but Symfony silently complains (in Symfony toolbar/Doctrine/Entities Mapping > Mapping errors) with:
App\Entity\User
The mappings App\Entity\User#time2 and App\Entity\Time#user are inconsistent with each other.
Obviously, Doctrine doesn't like the second #ORM\OneToOne on $user, and is discarding it.
What hypotethical misbehaviours could this code lead to?
Note: doctrine/common v2.11
FWIW, it is possible to make this relation, as far as one renounces to make a Bidirectional Association:
User Time
+----------+ +-------+
| ... | | ... |
| time_id |o-----+-----o| |
| | | | |
| time2_id |o-----+ | type |
| ... | +-------+
+----------+
implemented by:
class Time
{
...
}
class User
{
...
/**
* #ORM\OneToOne(targetEntity=Time::class, cascade={"persist"})
* #ORM\JoinColumn(name="time_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
*/
private $time;
/**
* #ORM\OneToOne(targetEntity=Time::class, cascade={"persist"})
* #ORM\JoinColumn(name="time2_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
*/
private $time2;
...}
Also look at this link for Owning vs Inverse relations.
In my case, this totally fits my needs, as the inverse part is for methods like:
$Time->getUser();
which I can prescind of.

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

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