CActiveDataProvider Querying on join - yii

I have a simple SQL query, which I need to convert to use in Yii 1.1.
SELECT *
FROM User
INNER JOIN Role ON Role.UserId = User.Id
WHERE Role.Name = 'admin'
How is this written into the CActiveDataProvider?

I have came up with an answer. Hopefully it helps someone in the future.
$dataProvider = new ActiveDataProvider('User', array
(
'criteria' => array
(
'with' =>'roles',
'join' => 'INNER JOIN Role r ON r.UserId = User.Id',
'condition' => 'r.Name=:term',
'params' => array(':term'=>'admin')
)
));

Related

Cakephp: Group by foreign key id and order by published date

public function index() {
$this->paginate = array(
'order'=>array('published_date'=>'desc'),
'group'=>'book_id',
'conditions'=>array('Chapter.published'=>1,'Chapter.published_date <= NOW()')
);
$chapters = $this->paginate();
$this->set('chapters',$chapters);
}
My database have table Book, Chapter. Each book has many chapter
Table Chapter has field '*book_id*', that is foreign key reference table Book primary key (id).
Here is my index page. The idea is to get latest chapter from each book and order by published date.In controller ChapterController, I use group by statement but it didn't get the latest chapter, it get the first chapter form each book.
So,please help me fix it. Thanks a lot
I believe that group by will use the first row that is naturally in your results, and I do not think there is a simple way to sort your results before the group by is applied. But I think the following query will get you the results you want:
SELECT * FROM books INNER JOIN (SELECT * FROM chapters WHERE chapters.published = 1 AND chapters.published_date <= NOW() ORDER BY chapters.published_date DESC) AS Chapter ON Chapter.book_id = books.id GROUP BY books.id
I think the following is how the CakePHP should look (I'm assuming you're paginating Book):
$this->Book->recursive = -1; //Join manually instead
$this->paginate = array(
'order' => array('published_date' => 'desc'),
'group' => 'Book.id',
'joins' => array(
array(
'table' => '(SELECT * FROM chapters)',
'alias' => 'Chapter',
'conditions' => array(
'Chapter.book_id = Book.id',
'Chapter.published' => 1,
'Chapter.published_date <= NOW()',
),
'type' => 'inner',
'order' => array('published_date' => 'desc'),
),
),
);

how to get data from inner join using cdbcriteria in yii?

This is my SQL. I want to create a CDbCriteria in Yii.
select us.user_id,u.clientid from user_session us
inner join user u on u.id=us.user_id
where us.auth_token='authtoken0000000001'
I tried this, but gives the wrong result. I also defined a relation related in my user_session model for this.
$criteria = new CDbCriteria;
$criteria->select = "user_id,user.clientid as client_id";
$criteria->condition='auth_token="'.$token.'"';
$clientIdarray = UserSession::model()->with('related')->find($criteria);
$dataprovider=New CActiveDataProvider('Bla',
array(
'criteria'=>array(
'order'=>'id ASC',
'with'=>array(
'user',
),
'joinType'=>'INNER JOIN',
'condition'=>'user.auth_token = '.$token,
)
));
Just an example how to do dataprovider init.
$criteria->with do what you need.
This topic will help. http://www.yiiframework.com/doc/guide/1.1/en/database.arr

Cakephp pagination with joined tables

I want to join the "sectors" table to my pagination results. Here is what happens:
I set the paginate variable so that it will join Sector:
$this->paginate = array(
'joins' => array(
array(
'table' => 'sectors',
'alias' => 'Sector',
'type' => 'left',
'foreignKey' => false,
'conditions' => array('Company.sector_id = Sector.id'))),
'conditions' => $conditions);
and then go
$jobs = $this->paginate('Job');
The query generated by the paginator is corrupted because it joins Sector before Company.
Here is the part of the sql output:
SELECT COUNT(*) AS `count` FROM `jobs` AS `Job` left JOIN sectors AS `Sector` ON (`Company`.`sector_id` = 'Sector.id') LEFT JOIN `companies` AS `Company` ON (`Job`.`company_id` = `Company`.`id`)
and it should be:
SELECT COUNT(*) AS `count` FROM `jobs` AS `Job` LEFT JOIN `companies` AS `Company` ON (`Job`.`company_id` = `Company`.`id`) left JOIN sectors AS `Sector` ON (`Company`.`sector_id` = 'Sector.id')
I paginate the Job model and it is related to the Company model but not the Sector model. Thats why I need to join the Sector with pagination.
How can I fix this?
'Joins' conditions in CakePHP should not be specified as an associative array, but as a string, otherwise CakePHP will handle 'Sector.id' as a literal string not as a reference to another Model/field.
So, replace this:
'conditions' => array('Company.sector_id' => 'Sector.id')
With this
'conditions' => array('Company.sector_id = Sector.id')
And your query should be ok
My solution is to join the Job model with the Sector.

converting sql query into cakephp format

Hi
i need the following sql query into cakephp find() format. the query it self is working fine but i need to change it.
$this->Part->query(
"SELECT `parts`.`id`,`parts`.`part_name`
FROM `parts`
LEFT JOIN (
SELECT `op` . *
FROM `order_parts` AS `op`
WHERE `op`.`order_id` =".$this->Session->read('orderid')."
) AS `vT`
ON ( `parts`.`id` = `vT`.`part_id` )
WHERE `vT`.`part_id` IS NULL"
);
thanks
If your relationship are Order HABTM Part and you have a table orders_parts with columns: id, order_id,part_id you should be able to do something like this:
First, get the ids of the parts which are in the order:
//each Part has one OrdersPart per order
$this->Part->bindModel(array('hasOne' => array('OrdersParts')));
$parts = $this->Part->find('list', array(
'fields' => array('Part.name'),
'conditions' => array(
'OrdersParts.order_id' => $this->Session->read('orderid'),
),
'recursive' => 2
));
Now get the parts which are not in the order:
$this->Part->find('all', array(
'conditions' => array(
"NOT" => array('Part.id' => array_keys($parts))
),
));

Conditions with And Or statements

I got this figured out. Here is the solution:
'conditions'=>array(
'OR' => array(
array('EavAttribute.attribute_code'=>'lastname'),
array('EavAttribute.attribute_code'=>'firstname')
),
'AND' => array(
array('UserEntityVarchar.entity_id'=>$id)
)
)
I am trying to convert this query into a cakephp query and I am having a bit of trouble with the conditions. No matter how I format the conditions, I always end up with the second query below.
Any help with this is greatly appreciated.
This is the query I am trying to replicate:
SELECT
`UserEntityVarchar`.`value_id`,
`UserEntityVarchar`.`attribute_id`,
`UserEntityVarchar`.`entity_id`,
`UserEntityVarchar`.`value`,
`EavAttribute`.`attribute_code`
FROM
`user_entity_varchars` AS `UserEntityVarchar`
LEFT JOIN `eav_attributes` AS `EavAttribute` ON(
`UserEntityVarchar`.`attribute_id` = `EavAttribute`.`attribute_id`)
WHERE
(UserEntityVarchar.entity_id = 1 AND
EavAttribute.attribute_code = 'firstname') OR
(UserEntityVarchar.entity_id = 1 AND
EavAttribute.attribute_code = 'lastname')
This is the query I keep getting no matter how I format my condition:
SELECT
`UserEntityVarchar`.`value_id`,
`UserEntityVarchar`.`attribute_id`,
`UserEntityVarchar`.`entity_id`,
`UserEntityVarchar`.`value`,
`EavAttribute`.`attribute_code`
FROM
`user_entity_varchars` AS `UserEntityVarchar`
LEFT JOIN `eav_attributes` AS `EavAttribute` ON(
`UserEntityVarchar`.`attribute_id` = `EavAttribute`.`attribute_id`)
WHERE
((`UserEntityVarchar`.`entity_id` = 1)
AND
(`EavAttribute`.`attribute_code` = 'firstname'))
AND
((`UserEntityVarchar`.`entity_id` = 1)
AND
(`EavAttribute`.`attribute_code` = 'lastname'))
This is the condition that I am using:
'conditions'=>array(
array(
array('UserEntityVarchar.entity_id'=>$id),
array('AND ' => array('EavAttribute.attribute_code'=>'firstname'))
),
array('OR' =>
array('UserEntityVarchar.entity_id'=>$id),
array('AND ' => array('EavAttribute.attribute_code'=>'firstname'))
)
)
You should be able to do it like this:
$this->Model->find('all', array('conditions' => array('OR' => array(
array('UserEntityVarchar.entity_id' => 1,
'EavAttribute.attribute_code' => 'firstname'),
array('UserEntityVarchar.entity_id' => 1,
'EavAttribute.attribute_code' => 'lastname')))));