Many to many relation on the same table - symfony1

I'm trying to setup a m2m relation between 'Gabarits'.
One gabarit can have many Gabarits ( called Options )
One gabarit can come from many Gabarits ( called OptionsFrom )
Here is my schema.yml:
Gabarit:
actAs: [Attachable]
columns:
libelle: { type: string, size: 255 }
description: { type: clob }
relations:
Options:
class: Gabarit
refClass: Gabarit2Gabarit
local: gabarit_id
foreign: fils_id
foreignAlias: OptionsFrom
Gabarit2Gabarit:
columns:
fils_id: { type: integer, primary: true }
gabarit_id: { type: integer, primary: true }
relations:
Gabarit:
class: Gabarit
local: gabarit_id
alias: Gabarit
foreignAlias: Gabarit2Gabarits
Fils:
class: Gabarit
local: fils_id
alias: Fils
foreignAlias: Gabarit2Gabarits
Generated code is:
$this->hasMany('Gabarit as Options', array(
'refClass' => 'Gabarit2Gabarit',
'local' => 'gabarit_id',
'foreign' => 'fils_id'));
$this->hasMany('Gabarit as OptionsFrom', array(
'refClass' => 'Gabarit2Gabarit',
'local' => 'fils_id',
'foreign' => 'gabarit_id'));
It seems good, according to http://www.doctrine-project.org/projects/orm/1.2/docs/manual/defining-models/en#relationships:join-table-associations:self-referencing-nest-relations:non-equal-nest-relations
Logically, it would give me this:
foreach($gabarit_>getOptions() as $option)
{
in_array($gabarit->getId(), $options->getOptionsFrom()->getPrimaryKeys()); // should be true but returns false !!
}
Generated SQL for getOptions() :
SELECT gabarit.id AS gabarit__id, gabarit.libelle AS gabarit__libelle, gabarit.description AS gabarit__description, gabarit2_gabarit.fils_id AS gabarit2_gabarit__fils_id, gabarit2_gabarit.gabarit_id AS gabarit2_gabarit__gabarit_id FROM gabarit INNER JOIN gabarit2_gabarit ON gabarit.id = gabarit2_gabarit.fils_id WHERE gabarit.id IN (SELECT fils_id FROM gabarit2_gabarit WHERE gabarit_id = '507') ORDER BY gabarit.id ASC
Generated SQL for getOptionsFrom() :
SELECT gabarit.id AS gabarit__id, gabarit.libelle AS gabarit__libelle, gabarit.description AS gabarit__description, gabarit2_gabarit.fils_id AS gabarit2_gabarit__fils_id, gabarit2_gabarit.gabarit_id AS gabarit2_gabarit__gabarit_id FROM gabarit INNER JOIN gabarit2_gabarit ON gabarit.id = gabarit2_gabarit.gabarit_id WHERE gabarit.id IN (SELECT gabarit_id FROM gabarit2_gabarit WHERE fils_id = '529') ORDER BY gabarit.id ASC
Do you have any idea why Gabarit::getOptionsFrom returns an empty collection ?
thanks in advance,
Florian.

It will most probably be the fact that you are using the same alias
foreignAlias: Gabarit2Gabarits
Your Gabarit2Gabarit should be like this:
Gabarit2Gabarit:
columns:
fils_id: { type: integer, primary: true }
gabarit_id: { type: integer, primary: true }
relations:
Gabarit:
class: Gabarit
local: gabarit_id
alias: Gabarit
foreignAlias: Gabarit2GabaritsGabarit
Fils:
class: Gabarit
local: fils_id
alias: Fils
foreignAlias: Gabarit2GabaritsFils
That might help?

Related

How order doctrine query for many-to-many relationship?

i use doctrine 1.2 and here is my schema:
ProviderProduct:
columns:
provider_id:
type: integer
primary: true
product_id:
type: integer
primary: true
num:
type: integer
default: 0
unsigned: true
Provider:
columns:
name: {type: string(255), notnull: true, notblank: true, unique: true}
relations:
Products:
class: Product
local: provider_id
foreign: product_id
refClass: ProviderProduct
Product:
columns:
#a lot of columns
relations:
Providers:
class: Provider
local: product_id
foreign: provider_id
refClass: ProviderProduct
What i want is get product with max num (this is ammount) for specific provider.
I tried this query:
$query = Doctrine_Query::create()->select('p.*')
->from('Product p')
->innerJoin('p.Providers pr')
->where('pr.name = ?', 'WhiteStore')
->orderBy('ProviderProduct.num');
$query->fetchOne();
The result sql query:
SELECT p.* FROM product p
INNER JOIN provider_product p3 ON (p.id = p3.product_id)
INNER JOIN provider p2 ON p2.id = p3.provider_id, provider_product p4
WHERE (p2.name = ?) ORDER BY p4.num
As you can see it doesnt order by num field. So, what is the right dql for my task ?
How order doctrine query for many-to-many relationship?
You can use following construction:
$query = Doctrine_Query::create()->select('p.*')
->from('Product p')
->innerJoin('p.Providers pr')
->where('pr.name = ?', 'WhiteStore')
->orderBy('p.Providers.ProviderProduct.num');
The not native behavior of Doctrine 1 is creating an invisible alias for many-to-many relation. You can use this alias for building right order.
I think you need to relate refClass too:
ProviderProduct:
columns:
provider_id:
type: integer
primary: true
product_id:
type: integer
primary: true
num:
type: integer
default: 0
unsigned: true
relations:
Provider: { foreignAlias: ProviderProduct }
Product: { foreignAlias: ProviderProduct }
And then relate through reffClass to get the number:
$query = Doctrine_Query::create()->select('p.*')
->from('Product p')
->innerJoin('p.ProviderProduct pp')
->innerJoin('pp.Provider pr')
->where('pr.name = ?', 'WhiteStore')
->orderBy('pp.num DESC') // to get de max first
->groupBy('p.id') // if any duplicates
->limit(1);
$product = $query->fetchOne();

Symfony (Doctrine) : Fixtures one to many relation with custom fields

I'm looking to create fixtures file for the following schema (Movies library):
VodProgram:
actAs: { Timestampable: ~ }
columns:
title: { type: string(255), notnull: true }
year: { type: smallint }
...
relations:
VodPersons:
class: VodPerson
refClass: VodCasting
local: program_id
foreign: person_id
foreignAlias: VodPrograms
VodPerson:
columns:
name: { type: string(255), notnull: true }
VodCasting:
columns:
program_id: { type: integer, primary: true }
person_id: { type: integer, primary: true }
role: { type: string(255) }
rank: { type: smallint }
relations:
VodProgram: { onDelete: CASCADE, local: program_id, foreign: id }
VodPerson: { onDelete: CASCADE, local: person_id, foreign: id }
My problem is creating fixtures file with the "role" and "rank" fields present in the VodCasting table.
Here is my actual fixtures:
VodPerson:
kosinski:
name: Joseph Kosinski
VodProgram:
tron:
VodPersons: [kosinski] # where to put the role and rank infos ?
title: Tron
year: 2010
I tried something like :
VodProgram:
tron:
VodPersons:
kosinski:
rank: 1
title: Tron
...
with no luck.
Any suggestions?
Thanks.
Have you tried something like that :
VodPerson:
kosinski:
name: Joseph Kosinski
VodProgram:
tron:
title: Tron
year: 2010
VodCasting:
tron_kosinski:
role: 'Director'
rank: 1
VodPerson: kosinski
VodProgram: tron

Symfony sorted model with having request

I have two models : Operation and OperationHistory
Operation:
columns:
startdate: { type: timestamp, notnull: true }
enddate: { type: timestamp, notnull: true }
year: { type: integer, notnull: true }
abscomment: { type: string(500) }
person_id: { type: integer, notnull: true }
operationtype_id: { type: integer, notnull: true }
relations:
Person: { onDelete: CASCADE, local: person_id, foreign: id, foreignAlias: Operations}
OperationType: { onDelete: CASCADE, local: absencetype_id, foreign: id, foreignAlias: Operations }
OperationHistory:
columns:
oh_comment: { type: string(500), notnull: true }
oh_date: { type: timestamp, notnull: true }
status_id: { type: integer, notnull: true }
operation_id: { type: integer, notnull: true }
updater: { type: integer, notnull: true }
indexes:
date:
fields:
ohdate:
sorting: DESC
relations:
Operation: { onDelete: CASCADE, local: operation_id, foreign: id, foreignAlias: OperationsHistory }
Person: { onDelete: CASCADE, local: updater, foreign: id, foreignAlias: OperationsHistory }
OperationStatus: { onDelete: CASCADE, local: status_id, foreign: id, foreignAlias: OperationsHistory }
In order to get all Operation by Person, I use an index on OperationHistory. So if I need all the person's operation with a specific status:
public function getOperations($person, $status){
$q = $this->createQuery('o')
->leftJoin('o.OperationsHistory oh')
->leftJoin('p.Person p')
->groupBy('ah.absence_id')
->having('ah.status_id = ?', $status);
return $q->execute();
}
Thanks to the index on ohdate, I assume with the groupBy, I only get the last OperationHistory about a specific Operation. Without the having clause, It's good, but I only want Operations with a specific Status. But if I set this having clause, I get nothing at all.
In fact, I need to translate this sql request :
SELECT *
FROM operation o
LEFT JOIN (
SELECT *
FROM operation_history
ORDER BY ohdate DESC
) oh ON o.id = oh.absence_id
LEFT JOIN person p ON p.id = o.person_id
WHERE p.id = 1
GROUP BY oh.operation_id
HAVING oh.status_id = 1
sorry for my bad english and I hope these informations will be usefull to help me.
Thank u !
Its very difficult to understand what you are trying to do just based on your questions above - can you include some other information ?
You can use join and orderby methods of the Doctrine_Query class :
$query = Doctrine_Core::getTable('operation')->createQuery()
->innerjoin('operation_history ......')
->orderby('.....')
By using Doctrine_RawSql(), it works !
public function getAbsenceQueries($person, $status){
$q = new Doctrine_RawSql();
$q->select('{o.*}, {oh.*}')
->from('operation o LEFT JOIN (SELECT * from operation_history order by ohdate DESC) oh ON o.id=oh.operation_id LEFT JOIN person p ON p.id = o.person_id')
->where('mg.group_id = ?', $group)
->groupBy('ah.absence_id')
->having('ah.status_id = ?', $status)
->addComponent('o','Operation o')
->addComponent('oh','o.OperationsHistory oh')
->addComponent('p','o.Person p');
return $q->execute();
}

doctrine many-to-many not working

I've got the following schema.yml file, but it's just not working correctly. Can anyone point me in the right direction please?
ClientPaymentService:
actAs: { Timestampable: ~ }
columns:
clientId: integer
name: { type: string(100), notnull: true, unique: true }
paymentServiceId: integer
config: { type: string(4096), notnull: true }
cardFormatId: integer
relations:
Client:
local: clientId
foreign: id
type: many
foreignType: one
foreignAlias: Client
PaymentService:
local: paymentServiceId
foreign: id
type: many
foreignType: one
foreignAlias: ClientPaymentService
CardFormat:
local: cardFormatId
foreign: id
type: many
foreignType: one
foreignAlias: ClientCardFormats
CountryCode:
class: CountryCode
refClass: ClientPaymentServiceCountryCode
foreign: id # country_code_id also doesn't work
local: id
ClientPaymentServiceCountryCode:
columns:
client_payment_service_id:
type: integer
primary: true
country_code_id:
type: integer
primary: true
relations:
ClientPaymentService:
local: client_payment_service_id
foreign: id
foreignAlias: ClientPaymentServiceCountryCodes
CountryCode:
local: country_code_id
foreign: id
foreignAlias: ClientPaymentServiceCountryCodes
CountryCode:
actAs: { Timestampable: ~ }
columns:
name: { type: string(100), notnull: true, unique: true }
code: { type: string(10), notnull: true, unique: true }
relations:
ClientPaymentService:
class: ClientPaymentService
refClass: ClientPaymentServiceCountryCode
local: id
foreign: id # client_payment_service_id also doesn't work
I receive the following error when trying to save something in the admin area:
Unknown record property / related component "id" on "ClientPaymentServiceCountryCode"
Thanks
Try this association:
ClientPaymentService:
.....
CountryCode:
class: CountryCode
refClass: ClientPaymentServiceCountryCode
foreign: country_code_id # country_code_id also doesn't work
local: client_payment_service_id # you must define both directions
ClientPaymentServiceCountryCode:
columns:
client_payment_service_id:
type: integer
primary: true
country_code_id:
type: integer
primary: true
// you not have to define relations here
CountryCode:
....
ClientPaymentService:
class: ClientPaymentService
refClass: ClientPaymentServiceCountryCode
local: country_code_id
foreign: client_payment_service_id
I have just follow documentation :
http://www.doctrine-project.org/projects/orm/1.2/docs/manual/defining-models/ru#relationships:join-table-associations:many-to-many

Symfony doctrine , unique records

I use symfony 1.4.11 with doctrine.This is one of my tables:
Subscriptions:
connection: doctrine
tableName: subscriptions
columns:
user_id: { type: integer(4), primary: true }
category_id: { type: integer(4), primary: true }
relations:
sfGuardUser: { onDelete: CASCADE, local: user_id, foreign: id }
Categories: { onDelete: CASCADE, local: category_id, foreign: category_id }
I need to get all user_id from this table.
I make :
public function getSubscriptionsUser()
{
$q = $this->createQuery('a')
->select ('a.user_id');
return $q-> execute();
}
But if the user is subscribed to several categories, its id will be repeated several times. Is it possible to extract only unique id of user? If user have id = 1 , and it is repeated 10 times,in result I will have only "1" , but no "1 1 1 1 1 1 1 1 1 1" :-)
Thank you!
This should work out for you:
$q = $this->createQuery('a')
->select ('distinct(a.user_id) as user_id');

Resources