I have the following ORM:
AppBundle\Domain\ValueObject\Date\Birthday:
type: embeddable
fields:
birthday:
column: fecha_nacimiento
type: datetime
And I want to use this value object in two tables, the first is "User" table:
AppBundle\Domain\Entity\User\User:
type: entity
table: usuarios_web
repositoryClass: AppBundle\Infrastructure\Persistence\Doctrine\Repository\User\UserDoctrineRepository
embedded:
birthday:
class: AppBundle\Domain\ValueObject\Date\Birthday
columnPrefix: false
But then I want to use the same birthday on another table who's birthday field is not "fecha_nacimiento", is different.
It's possible to map the DB field in the emmbedded instead of the embeddable?
Related
I'm using Doctrine with YML mappings. I have two entities. One Group entity and one User entity.
I'm trying to set it up so Users have unique names within a group.
I can create a User, assign it a Group, and save it to the DB. But when I try to create a User with the same name and a different Group, then I get an error saying the unique constraint on name is violated.
Why can't I persist that User?
Their mappings look like this:
Entity\Group:
type: entity
table: groups
id:
id:
type: guid
nullable: false
id: true
generator:
strategy: AUTO
fields:
name:
type: text
nullable: true
Entity\User:
type: entity
table: users
id:
group:
associationKey: true
nullable: false
name:
type: string
manyToOne:
Group:
targetEntity: Entity\Group
joinColumn:
name: group
referencedColumnName: id
I eventually figured this out. I was confusing Doctrine.
The non-standard thing was that I'm using a capitalized parameter name to represent an object and changing that to lowercase for the table column. I did this in the manyToOne: section using name:.
The documentation doesn't really do this, so I didn't know that I still had to reference the capitalized property name in the id: section and separately define the column name there.
So, I changed the User mapping to this:
Entity\User:
type: entity
table: users
id:
Group:
column: group
associationKey: true
nullable: false
name:
type: string
manyToOne:
Group:
targetEntity: Entity\Group
joinColumn:
name: group
referencedColumnName: id
There is a User class which has two types of users such as patient and doctor. So, I created another attribute that is used to describe the relation between patient and doctor, a doctor can have many patients. So, If the user is patent, he should have doctorId, if not, the doctorId is NULL.
Here is my User.orm.yml:
Acme\Bundle\DemoBundle\Entity\User:
type: entity
table: User
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
name:
type: string
length: 30
lastName:
type: string
length: 30
email:
type: string
length: 60
unique: true
username:
type: string
length: 10
unique: true
password:
type: string
length: 100
unique: false
doctorId:
type: integer
unique: false
nullable: true
dateCreated:
type: datetime
manyToMany:
roles:
targetEntity: Role
mappedBy: users
How can I map the doctorId as a foreign key that refers to the id?
You can find instructions for self-referencing One-To-Many relations in the Doctrine documentation:
User:
type: entity
oneToMany:
patients
targetEntity: User
mappedBy: doctor
manyToOne:
doctor:
targetEntity: User
inversedBy: patients
http://docs.doctrine-project.org/en/latest/reference/association-mapping.html#one-to-many-self-referencing
With doctrine you might want to take a look at association mapping. http://docs.doctrine-project.org/en/latest/reference/association-mapping.html. In your case you are after a one to many self referencing relationship http://docs.doctrine-project.org/en/latest/reference/association-mapping.html#one-to-many-self-referencing.
A doctor can have many patients but can a patient have many doctors? If so you have a many to many relationship which you could map out using a cross Reference table as the joining table. The best way to model this I feel is to have a userTypeId in your users Table where a value of 1 could be doctor, 2 a patient etc. Then a doctor can have many patients but also a patient can see many doctors. This would also be extensible if you added new user types like nurses etc.
I have two entities, invoices and sales tax. Recently my team has decided to upgrade to Symfony 2.3 from 2.1. We had to rewrite a lot of the ways we were doing queries because of this, and some entities that didn't have relationships needed to have them.
Before the update, my invoices and sales tax records were created by getting the transaction id date('U'); and setting up both with the same transaction id (both tables have a primary index id as well).
So you can imagine it looks like this:
Sales Tax: id, transaction_id, amount
Invoice: id, transaction_id, amount
So when I queried for them I just joined on the transaction id. Now joins aren't working without relationships, so I'm having to update this to have a relationship. But when I go to create an invoice or sales tax record, I get this error: Notice: Undefined index: transactionId in C:\folders\vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\BasicEntityPersister.php line 539.
In the code the sales tax record is being created just fine, but when it goes to create the invoice it fails:
public function insertSalesTax($transactionId, $amount)
{
$tax = new SalesTax();
$tax->setAmount($amount);
$tax->setTransactionId($transactionId);
$this->entityManager->persist($tax);
$this->entityManager->flush();
return $tax;
}
That inserts, but then I take that tax record and try to create the invoice:
$invoice = new Invoice();
$em = $this->entityManager;
$invoice //omitted other invoice data
->setSalesTax($salesData['salesTax']);
$em->persist($invoice);
$em->flush();
Here's the relevant portions of my mapping in yml:
Bundle\Entity\Invoice:
type: entity
table: invoices
indexes:
transactionId:
columns: [ transaction_id ]
id:
id:
type: integer
generator: { strategy: AUTO }
manyToOne:
salesTax:
targetEntity: SalesTax
inversedBy: invoice
joinColumn:
name: transaction_id
referencedColumnName: transaction_id
And SalesTax:
Bundle\Entity\SalesTax:
type: entity
table: sales_taxes
indexes:
transactionId:
columns: [ transaction_id ]
id:
id:
type: integer
generator: { strategy: AUTO }
oneToMany:
invoice:
targetEntity: Invoice
mappedBy: salesTax
If you're wondering why oneToMany, that's because invoices are stored as individual line items. There may be many invoices with the same transaction ID. One transaction ID in the invoices table represents one order, each row only represents a line item. So this invoice entity will probably need a self-referencing relationship at some point.
I am having an issue with the primary key of a mapped entity not being detected by doctrine.
I have 2 tables, users and operators. There is a unidirectional many to one relationship between users and operators.
User entity is defined as
XXX\SecurityBundle\Entity\User:
type: entity
repositoryClass: XXX\SecurityBundle\Repository\UserRepository
table: XXX_USER
id:
id:
type: integer
unsigned: false
nullable: false
column: ID
generator:
strategy: AUTO
fields:
username:
type: string
length: 32
nullable: false
column: USERNAME
...
manyToOne:
operator:
targetEntity: XXX\CoreDataBundle\Entity\Operator
joinColumn:
name: operator_id
referencedColumnName: id
The operators entity defined as
XXX\CoreDataBundle\Entity\Operator:
type: entity
respositoryClass: XXX\CoreDataBundle\Repository\OperatorRepository
table: OPERATORS
id:
id:
type: integer
unsigned: false
nullable: false
column: ID
generator:
strategy: AUTO
fields:
operName:
type: string
length: 32
nullable: false
column: OPERATOR_NAME
When validating the schema, I receive the following error :
The referenced column name 'id' has to be a primary key column on the target entity class 'XXX\CoreDataBundle\Entity\Operator'.
When I try to assign an operator to a user, I receive the following error :
[ErrorException]
Notice: Undefined index: id in vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php line
607
As far as I can see, 'id' is set as the primary key of the operator entity. The database behind doctrine is oracle, in is in sync with the entity definitions and the primary key is set correctly on the database.
Anyone able to spot my error in defining the mapping ?
I do not think the fact the entities are in different bundles is an issue as I am getting similar issues with entities in the same bundle.
Thank you.
Oracle's columns and table names are always uppercase. So if using them, you need to put the referencedColumnName in uppercase even if in the PHP side it is lowercase.
I have a Stats entity that is related to a Journey entity through a ManyToOne association.
id:
index:
type: integer
fields:
idJourney:
type: string
// data fields...
manyToOne:
journey:
targetEntity: Journey
joinColumn:
name: idJourney
referencedColumnName: idJourney
The Journey is related to the Station entity through two ManyToOne association: one for the first Station of the Journey, one for the last.
id:
idjourney:
type: string
fields:
idFirstStation:
type: string
idLastStation:
type: string
// other info fields
manyToOne:
firstStation:
targetEntity: Station
joinColumn:
name: idFirstStation
referencedColumnName: idStation
lastStation:
targetEntity: Station
joinColumn:
name: idLastStation
referencedColumnName: idStation
Finally, the Station entity :
id:
idStation:
type: string
fields:
name:
type: string
// other station info
I retrieve a collection of Stats objects with all related sub-objects via a custom Repository method which works fine.
$statCollection = $statsRepository->getStatsByDateAndArea($date, $area);
//This retrieves the expected data
$statCollection[0]->getJourney()->getFirstStation()->getName();
However, iterating through the collection with a foreach loop doesn't work:
foreach($statCollection as $stat) {
$journey = $stat->getJourney(); // works fine
$firstStationId = $journey->getFirstStationId(); // works too
$firstStation = $journey->getFirstStation(); // still works, but returns a Proxies\AcmeAppPathWhateverBundleEntityStationProxy object instead of a AcmeAppPathWhateverBundleEntityStation, but this should be transparent (as per Doctrine documentation)
$firstStationName = $firstStation->getName(); // throws an EntityNotFoundException
}
Any idea what's going on ? Should I force Doctrine to fetch all sub entities ?
EDIT
The error message is fairly laconic :
EntityNotFoundException: Entity was not found.
Not very helpful...
I ended up querying explicitly for the full set of sub-entities in my custom repository method...
I changed this query :
->select('stats')
->leftJoin('stats.journey', 'j')
->leftJoin('j.firstStation', 'fs')
->leftJoin('j.lastStation', 'ls')
to :
->select('stats, j, fs, ls')
->leftJoin('stats.journey', 'j')
->leftJoin('j.firstStation', 'fs')
->leftJoin('j.lastStation', 'ls')
I guess Doctrine's use of Proxy objects are not all that transparent...