Doctrine Yaml Mapping Shared Columns - php

Is it possible using Yaml orm files to specify a base Entity that all of the Entities will share, I can compare this to C# ADO.NET where you can specify a class that holds all of the data that will be common among all of your tables
For example, say I have the below YAML mapping for Doctrine:
src\SITEBUNDLE\Entity\User:
REALTYBLOG\Entity\User:
type: entity
table: users
id:
id:
type:integer
generator: { strategy: AUTO }
fields:
firstName:
type: string
length: 255
lastName:
type: string
length: 255
middleInital:
type: string
length: 1
username:
type:
length: 26
passwordHash:
type: string
length: 255
createdOn:
type: dateTime
createdBy:
type: string
length: 26
modifiedOn:
type: dateTime
modifiedBy:
type: string
deletedOn:
type: dateTime
Now lets say that I have created multiple other YAML configs and all of them share the createdOn, createdBy, modifiedOn, modifiedBy, deletedOn columns. Can I specify an overlaying orm file that I can include in all of my orm files so I don't have to redundantly add them to every orm file?

Yes you can. It's quite simple.
TextItem:
columns:
topic: string(255)
Comment:
inheritance:
extends: TextItem
type: concrete
columns:
content: string(300)
More information: http://docs.doctrine-project.org/projects/doctrine1/en/latest/en/manual/yaml-schema-files.html -> inheritance / simple inheritance

Related

Cascaded persist not working (Doctrine ORM + Symfony 2)

I started working with symfony several months ago and there is one thing keeps bothering me all the time. It is when I have a one-to-many relationship in Doctrine and I try to insert something into the database. Here's an example:
Broker.orm.yml
Acme\DemoBundle\Entity\Broker:
type: entity
table: brokers
repositoryClass: BrokerRepository
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
name:
type: string
length: 255
slug:
type: string
length: 64
oneToMany:
accountTypes:
targetEntity: Acme\DemoBundle\Entity\AccountType
mappedBy: broker
cascade: ["persist"]
AccountType.orm.yml
Acme\DemoBundle\Entity\AccountType:
type: entity
table: account_types
repositoryClass: AccountTypeRepository
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
name:
type: string
length: 255
slug:
type: string
length: 64
manyToOne:
broker:
targetEntity: Acme\DemoBundle\Entity\Broker
inversedBy: accountTypes
joinColumn:
name: broker_id
referencedColumn: id
Then is try to save it to the database like this.
$accountType = new AccountType();
$accountType->setName("blabla");
// additional data to accountType
$broker->addAccountType($accountType);
$em->persist($broker);
$em->flush();
The strange thing is that it works prefrectly with only one tiny problem. Broker is updated, and AccountType is inserted into the database but the accountType doesn't have any relations with the Broker. In other words, when I check in the database the broker_id fields reamains untouched and contains NULL.
If I add $accountType->setBroker($broker) manually, it works. But I started to use Sonata Admin Bundle where there is much more complicated to do this and I don't really need a complex admin system. So I just want a fast development on it and without this "feature" it's nearly impossible.
And anyways, if I add something to a collection of an Object, it should know which object is its parent, right? :)
Thanks for your help in advance!
class Broker
{
public function addAccountType($accountType)
{
$this->accountTypes[] = $accountType;
// *** This is what you are missing ***
$accountType->setBroker($this);

select entities of multiple subclasses extending from one superclass using doctrine 2

Given this setup for my Doctrine 2 Entities:
App\Bundle\LorumBundle\Entity\Node:
type: entity
table: node
fields:
id:
id: true
type: integer
unsigned: false
nullable: false
generator:
strategy: IDENTITY
created:
type: datetime
inheritanceType: SINGLE_TABLE
discriminatorColumn:
name: type
type: string
length: 255
discriminatorMap:
a: a
b: b
c: c
App\Bundle\LorumBundle\Entity\A:
type: entity
fields:
status:
type: boolean
App\Bundle\LorumBundle\Entity\B:
type: entity
fields:
status:
type: boolean
App\Bundle\LorumBundle\Entity\C:
type: entity
fields:
title:
type: string
Now what I want to get is basically a mixed list of Entities of the type A & B (not C) with the status == true.
I could write a Query like this - using the instance ofoperator to limit the result to the subclasses i want of course but i will get an Error because the property I want to match against (status) is not mapped in the Superclass even tough all the Entities i want to match against have it:
$queryBuilder->select('Node');
$queryBuilder->from('App\Bundle\LorumBundle\Entity\Node','Node');
$queryBuilder->add('where',$queryBuilder->expr()->orx(
'Offer INSTANCE OF AppLorumBundle:A',
'Offer INSTANCE OF AppLorumBundle:B'
));
$queryBuilder->where($queryBuilder->expr()->eq('Node.status', '?1'));
$queryBuilder->setParameter(1, true);
$queryBuilder->orderBy('Node.created', 'asc');
$queryBuilder->setFirstResult( 0 );
$queryBuilder->setMaxResults( 200 );
Is there any way to do this, short of writing your own persister and hack it into Doctrine2?
Unfortunately its not an Option for me to just add the Information to the Superclass (in my real scenario this situation mostly applies to relations which i don't want to be loaded eagerly with every subclass)
You can use UNION and work with queries for entities A and B
build query for entity A
build query for entity B
build query for limit and order using UNION for queries A and B
no need to do any hacks for Doctrine library

Doctrine 1.2 class self reference in Postgres throws SQL error on save

I'm trying to model a user which could be invited by another user. So I set up one-to-many self reference in my doctrine model.
User:
tableName: users
actAs:
Timestampable:
columns:
id:
type: integer(11)
primary: true
autoincrement: true
name:
type: string(255)
unique: true
password:
type: string(255)
email:
type: string(255)
[...]
invited_by:
type: integer(11)
relations:
Inviter:
class: User
type: one
local: invited_by
foreign: id
foreignAlias: Invitees
onDelete: SET NULL
onUpdate: CASCADE
options:
type: InnoDB
collate: utf8_unicode_ci
charset: utf8
This works just fine in MySQL, but if I try to save the record using the User objects save()-method in Postgres the following error is thrown:
SQLSTATE[42P01]: Undefined table: 7 FEHLER: Relation »users_id«
existiert nicht LINE 1: SELECT CURRVAL('users_id') ^. Failing Query:
"SELECT CURRVAL('users_id')"
I think it is something related to the self reference, but I can't find a mistake in my modeling. Anyone an idea on this?
The default name of a sequence attached to a serial column is tablename_colname_seq
currval is for retrieving the "current value" of a sequence.
So it would have to be:
SELECT currval('users_id_seq')
Your whole syntax is obviously made out for MySQL. Things like type: InnoDB, integer(11) or autoincrement don't make sense in Postgres.

Use of "Container" as model name in Symfony

I have a entity called Container in a Symfony application, which I have included in the schema.yml file:
Container:
columns:
id: { type: integer, primary: true, autoincrement: true }
name: { type: string(127), notnull: true }
Strain:
columns:
id: { type: integer, primary: true, autoincrement: true }
...
container_id: { type: integer }
...
relations:
Container: { foreignAlias: Strains }
Then I have regenerated the models, forms and filters using the symfony doctrine:build --all-classes task.
Now when I try to use $strain->getContainer(), e.g. in a showSuccess action, it returns no object at all. I have double-checked that container_id has a reference to a record in container table.
Moreover, when I try to edit a Strain object and unlink the relationship with Container, the form is saved correctly, but the container_id column keeps the old value.
Do you know if Container is a reserved word or something like that in Symfony or Doctrine? What can be happening?
Thanks!
No, it isn't a reserved word.
(In fact, I have a model in my project with a Container relation).
Have you tried setting the local property on Container relation to container_id?

Doctrine : many to many with a date of assignation in the refclass

residentSector:
columns:
id_resident_sector:
type: integer
primary: true
autoincrement: true
id_resident:
type: integer(8)
id:
type: integer(8)
date:
type: timestamp
residents:
columns:
id_resident:
type: integer(8)
primary: true
autoincrement: true
firstname:
type: string(50)
lastname:
type: string(50)
relations:
Sectors:
class: Sectors
local: id_resident
foreign: id
refClass: residentSector
Sectors:
columns:
id:
type: integer(4)
primary: true
autoincrement: true
sector_name:
type: string(50)
id_resp:
type: integer(4)
visibility:
type: integer(1)
I want to select all the "residents" of a given "sector" at à given date (the lastest date as example).
My problem is the date field is in the refclass (because it's the date of assignation) so
->where('residents.Sectors.date =max(residents.Sectors.date) ')
won't work obviously because the refclass is not part of the collection ..
what is the good way to define the doctrine relation so i can get the latest sector in date of a resident ?
Thanks in advance !
Unfortunately Doctrine doesn't provide any built-in way to achieve what you're trying to do. However many-to-many relationship in fact uses double one-to-many relationship.
So what you need is to is:
Make correct DQL query:
Doctrine_Query::create()
->from('Residents r')
->innerJoin('r.XXX rs WITH rs.date = ?', '08-04-2010')
->innerJoin('r.Sector s');
Where XXX is the name of ResidentSector table. I'm not quite sure whether its name will be same as table name, but you can get its name from table definition generated by Doctrine.
After you execute the query you will have to do all the mapping by your own, using Doctrine_Record::mapValue.
I dont know how to use doctrine but having many to many relationships results in an abundance of duplicate data.
You should maybe have 3 tables (residents, sectors, residentsToSectors) have date assigned in the residentToSectors table and then grab the information for either resident or sector based on whatever data you insert in the WHERE clause?

Categories