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();
}
Related
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();
Perhaps an example would best describe my problem:
Schema:
Referral:
actAs: { timestampable: ~ }
columns:
id: { type: integer, primary: true, notnull: true, autoincrement: true, unique: true }
other_stuff: { type: string }
reasonCode: { type: integer }
relations:
ReasonCode: { local: reasonCode, foreign: id, foreignAlias: ReasonCodes }
ReasonCode:
columns:
id: { type: integer, primary: true, notnull: true, autoincrement: true, unique: true }
description: { type: string }
Query (referralTable.class.php):
public function getObjectByReferralId($id){
$q = Doctrine_Query::create()
->select('*')
->from('referral_submissions')
->where('referral_id=?', $id)
->fetchOne();
return $q;
}
Call in template:
<?php
$id = <source of id>;
echo Doctrine_Core::getTable('referral')->getObjectByReferralId($id)->getReasonCode();
?>
The above call in the template to get the reasoncode returns the "description" stored in the ReasonCode table, not the stored id in the Referral table. I need the actual id, not the joined description. What am I missing?
It's confusing because you named your foreign key with the name of your relation. So when you think you are getting the key, you fetch the relation. And I guess Doctrine do not retrieve the primary key since there is only one field in your ReasonCode table, so it returns the description field.
Try with :
Doctrine_Core::getTable('referral')
->getObjectByReferralId($id)
->get('reasonCode');
By the way, you also can retrieve the id using the relation:
Doctrine_Core::getTable('referral')
->getObjectByReferralId($id)
->getReasonCode()
->getId();
I think you should define your foreign key like : reason_code_id instead of reason_code. Then your schema will become:
Referral:
actAs: { timestampable: ~ }
columns:
id: { type: integer, primary: true, notnull: true, autoincrement: true, unique: true }
other_stuff: { type: string }
reasonCode_id: { type: integer }
relations:
ReasonCode: { local: reasonCode_id, foreign: id, foreignAlias: ReasonCodes }
And you will be able to retrieve the id using:
Doctrine_Core::getTable('referral')
->getObjectByReferralId($id)
->getReasonCodeId();
Hy guys
I've got the following schema for my objects:
Product:
columns:
name: { type: string(255) }
Basket:
columns:
current_status: { type: integer }
relations:
Products: { class: Product, refClass: BasketProducts, onDelete: CASCADE }
BasketProducts:
columns:
product_id: { type: integer, primary: true }
basket_id: { type: integer, primary: true }
quantity: { type: integer(4) }
relations:
Product: { local: product_id, onDelete: CASCADE }
Basket: { local: basket_id, onDelete: CASCADE }
Now in the frontend I try to show the users basket, getting the products by
foreach($basket->getProducts() as $product) {
echo $product->getId();
echo $product->getName();
}
The question now, how can i access the quantity field from the BasketProducts?
You will need to query the middle table directly in order to do this.
A good way to do this, is to add a function in your Basket.class.php that will retrieve the data you need based on a BasketID.
You could also create the function in your BasketTable.class.php if you'd like to include the data when fetching a particular basket (ie. getBasketWithProductQuantities())
I don't have any Doctrine code handy at this time.
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');
I'm setting up my first symfony project, and am having trouble with the schema. I'm not sure if I'm going about it the right way.
I'm having a problem with two of my classes. I have Clients, which can have many Contacts, one of the contacts needs to be selected as the invoice contact. This is my schema:
NativeClient:
actAs: { Timestampable: ~ }
columns:
name: { type: string(255), notnull: true }
address: { type: string(255) }
postcode: { type: string(9) }
tel: { type: string(50) }
fax: { type: string(50) }
website: { type: string(255) }
client_status_id: { type: integer, notnull: true, default: 0 }
priority: { type: boolean, notnull: true, default: 0 }
invoice_contact_id: { type: integer }
invoice_method_id: { type: integer }
relations:
NativeContact: { local: invoice_contact_id, foreign: id, foreignAlias: NativeInvoiceContacts }
NativeClientStatus: { local: client_status_id, foreign: id, foreignAlias: NativeContacts }
NativeInvoiceMethod: { local: invoice_method_id, foreign: id, foreignAlias: NativeClientStatuses }
NativeContact:
actAs: { Timestampable: ~ }
columns:
client_id: { type: integer, notnull: true }
name: { type: string(255), notnull: true }
position: { type: string(255) }
tel: { type: string(50), notnull: true }
mobile: { type: string(50) }
email: { type: string(255) }
relations:
NativeClient: { onDelete: CASCADE, local: client_id, foreign: id, foreignAlias: NativeClients }
NativeClientStatus:
actAs: { Timestampable: ~ }
columns:
name: { type: string(255), notnull: true }
NativeInvoiceMethod:
actAs: { Timestampable: ~ }
columns:
name: { type: string(255), notnull: true }
If i remove the following line (and associated fixtures) it works, otherwise I get a segmentation fault.
NativeContact: { local: invoice_contact_id, foreign: id, foreignAlias: NativeInvoiceContacts }
Could it be getting in a loop? Trying to reference the Client and the Contact over and over? Any help would be greatly appreciated! Thanks!
Darren
Old question I know, but heres a follow up solution. Sometimes Doctrine will throw this error for seemingly no reason whatsoever. Im sure there is an underlying reason, but we dont all have time to debug the entire Doctrine source.
Try specifying --env=[your env], and it may just work - has for me.
Darren, it seems like you're defining the relationship at both ends while using conflicting criteria...
NativeContact: { local: invoice_contact_id, foreign: id, foreignAlias: NativeInvoiceContacts }
...relationship is between "invoice_contact_id" and undeclared "id" PK in NativeContact.
NativeClient: { onDelete: CASCADE, local: client_id, foreign: id, foreignAlias: NativeClients }
... same relationship is between "client_id" and undeclared "id" PK in NativeClient.
I personally only define these in one end and let Doctrine handle the rest, but it depends on what you're trying to achieve here. If ONE client HAS MANY contacts, you could drop the second declaration and define the relationship in the clients table only and add "type: many, foreignType: one" to state that it's a one-to-many relationship.