My code :
$criteria = new CDbCriteria();
// $criteria->select = array("id");
$criteria->with = array('userProfiles'=>array(
'select'=>'firstname'
));
$criteria->together = true;
$criteria->condition = "firstname like '%$q%' "
. "and (user_id not in (select id2 from friends where id1=$user_id) "
. "and user_id not in (select id1 from friends where id2=$user_id))";
$dataProvider = new CActiveDataProvider("Users", array(
'criteria' => $criteria
));
return $dataProvider;
Notes:
1- userProfiles relation is defined in User module
Issue:
It is loading data only from User table not also from the user_profiles table despite of providing select atribute 'select'=>'firstname'
I want data from both user and userProfile table.
Relation self::HAS_ONE can't be executed together with main query, try use join
$criteria->select = "*, user_profiles.firstname firstname";
$criteria->join = 'user_profiles ON user_profiles.user_id = users.id';
Something like this, but you should create firstname field in User AR to retrieve it.
Or change relation to HAS_MANY and check first entity of array.
together: whether the table associated with this relationship should be forced to join together with the primary table and other tables. This option is only meaningful for HAS_MANY and MANY_MANY relations.
Because you can't write query that will give you only one record for each joining record
SELECT * FROM main
INNER JOIN slave ON (slave.main_id = main.id limit 1) // will not work);
Related
I have a query as follows:
SELECT messages.id,
messages.sender_id,
messages.subject,
messages.body,
messages.created_at,
user.username AS username
FROM messages LEFT JOIN user ON user.iduser=messages.sender_id
I tried to change the query to the CDbCriteria model's as follows:
$criteria = new CDbCriteria();
$criteria->select = "messages.id, messages.sender_id, messages.subject, messages.body, messages.created_at, user.username AS username";
$criteria->alias = "messages";
$criteria->join = "LEFT JOIN user ON user.iduser=messages.sender_id";
$messagesAdapter = Message::model()->findAll($criteria);
But, when I execute the query, appear error as follows:
Property "Message.username" is not defined.
What is an error in the query ?
Please help.
You should use relation name to print the username or user attributes, ie. user.*.
For that you should have relation in you Message model for User model.
Something like..
public function relations()
{
return array(
......
......
'userRel' => array(self::HAS_MANY, 'User', 'isuser'),
......
);
}
Now, you can print username using this relation name userRel
//check this
print_r($messagesAdapter[0]->userRel);
//May be you can get username with below statement as you are using left join
echo $messagesAdapter[0]->userRel[0]->username;
I am using a CListView to display my data on a page. I have a textbox for searching keywords in the query.
In my query where I build my CActiveDataProvider I have some subqueries. For Example:
$criteria = new CDbCriteria;
$criteria->select = array('
Lessons.id,
Lessons.name,
(SELECT
COALESCE(CONCAT(u.first_name, " ", u.last_name), last_name, first_name)
FROM
users AS u
WHERE
u.user_token = Lessons.instructor_id
) as instructor_name
');
My model for the above query does have a class variable called $instructor_name.
When I enter data into the textbox I then run this piece of code to join another table for searching.
if ( !empty($query) ) {
$criteria->with = array('packages');
$criteria->compare( 'packages.contents', $query, true);
$criteria->together = true;
}
The results when running a search query do not return the instructor_name data from the subquery.
Any ideas on what is happening here to prevent my subquery data from loading? Thank you in advance.
To do this in a more CActiveRecord way (and get the results your looking for), try the following:
1 - Add instructor relation to Lesson model that references the User table (so now you will be able to do $lesson->instructor)
'instructor'=>array(self::BELONGS_TO, 'User', 'instructor_id'),
2 - Add a column/expression into the select clause in your Lesson::search() method that represents the concatenated instructor_name - something like:
$criteria->select = array('
Lessons.id,
Lessons.name,
COALESCE(CONCAT(instructor.first_name, " ", instructor.last_name), last_name, first_name) AS instructor_name
...etc
3 - Add instructor to the "with" part of the search criteria so that the instructor info is joined into the query
$criteria->with = array('packages', 'instructor');
I have defined the following criteria in Yii, and tries to use it to fetch an array of customers.
$criteria = new CDbCriteria(array(
"condition"=>"hidden = 0".(Yii::app()->user->GetState('is_admin') ? "" : " AND franchisesMunicipalities.franchise_id=".Yii::app()->user->getState('fid')),
"with" => array('municipality','municipality.franchisesMunicipalities')
));
$customers = Customers::model()->findAll($criteria);
This (i thought) should result in that Yii joined the table Customers with the table Municipalities, and then in the same query join the table Municipalities with the table Franchises_Municipalities. However it doesn't work since it doesn't join franchisesMunicipalities.
The resulting query is this
SELECT `t`.`id` AS `t0_c0`,
`t`.`municipality_id` AS `t0_c1`,
`t`.`personal_code_number` AS `t0_c2`,
`t`.`name` AS `t0_c3`,
`t`.`adress` AS `t0_c4`,
`t`.`zip` AS `t0_c5`,
`t`.`phone` AS `t0_c6`,
`t`.`mobile` AS `t0_c7`,
`t`.`email` AS `t0_c8`,
`t`.`hidden` AS `t0_c9`,
`municipality`.`id` AS `t1_c0`,
`municipality`.`county_id` AS `t1_c1`,
`municipality`.`name` AS `t1_c2`
FROM `customers` `t`
LEFT OUTER JOIN `municipalities` `municipality`
ON ( `t`.`municipality_id` = `municipality`.`id` )
WHERE ( hidden = 0
AND municipality.franchisesmunicipalities.franchise_id = 7 )
LIMIT 30
As you can see it only joins on one relation. The relations in the model should be correctly defined, since i am able to use them in other contexts.
Why doesn't this work?
According to http://www.yiiframework.com/doc/api/1.1/CActiveRecord#with-detail I believe you should be doing it this way:
$criteria = new CDbCriteria(array(
"condition"=>"hidden = 0".(Yii::app()->user->GetState('is_admin') ? "" : " AND franchisesMunicipalities.franchise_id=".Yii::app()->user->getState('fid'))
));
$customers = Customers::model()->with('municipality','municipality.franchisesMunicipalities')->findAll($criteria);
Hopefully that works for you.
I am trying to do a Join query using CDBCriteria in Yii framework. The issue is the join query works successfully but it does not display the columns from other tables.
I am doing in the following way
$criteria = new CDbCriteria;
$criteria->order = 't.id desc';
$criteria->select = '*';
$criteria->join = ' INNER JOIN table2 INNER JOIN table3 INNER JOIN table4';
When i run this, I can see only the mail table1 columns displayed. Other columns are not shown.
In my model class, I have the relation has
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'user' => array(self::BELONGS_TO, 'DmPhoneUser', 'user_id'),
'command' => array(self::BELONGS_TO, 'DmOtaCommand', 'command_id'),
'partner' => array(self::BELONGS_TO, 'DmPartner', 'partner_id'),
);
}
********************************************************
public function actionGetHistory($start, $per_page)
{
$partner_id = '10';
$criteria = new CDbCriteria;
$criteria->order = 't.history_id desc';
$criteria->select = 't.*, table2.*';
$criteria->join = ' INNER JOIN table2 ON t.command_id = table2.command_id';
$result = Table_1_class::model()->with('command')->findAll();
$history_data = CJSON::encode($result);
echo $history_data;
}
here command_id is common in table1 and table2.
This is how I am using the criteria code.
As I said, Yii's Active Record implementation will only use columns which are defined in the table itself or the tables you are linking to through with, not arbitrary columns you return in the resultset.
Solution 1: Define a relation to table2, add that relation to with, and get rid of join. Then you'll probably need to convert each returned object to an array - CJSON::encode will not handle a model with relations well.
Solution 2: Use Yii::app()->db->createCommand("SQL query")->queryAll(); instead of Active Record. This will produce an array of arrays, which CJSON::encode will have no problem with.
I created 3 tables:
User
User-Group
Group
Where I can have a many-to-many relationship.
But how I create on the search method a find to it?
How can I get all users that have a specific group, like
select u.* from users as u, user-group as ug, group as g
where g.name = "group_1" and ug.group_id = g.id and ug.user_id = u.id ?
My code so far:
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'group'=>array(self::MANY_MANY, 'Group', 'tbl_profile(id_user, id_group)'),
'groupList' => array( self::HAS_MANY, 'Group', 'id_user' ),
}
$criteria->with=array('groupList' => array(
'condition' => 'id_user = 1',
));
I would start with the steps in this wiki article:
http://www.yiiframework.com/wiki/281/searching-and-sorting-by-related-model-in-cgridview/
Then, you'd need to add your join table groupID column to your gridviewand user search criterias. You will probably also need to add a with and together=true line to your search criteria.
Note that he has you add a new model attribute to your model to hold the search criteria. If you are using a drop down filter, you can specify your join table attributes' name directly.
User::model()->with(array(
'group'=>array(
'alias'=>'g',
'condition'=>'g.name=:gName',
'params'=>array(':gName'=>'group_1')
)
))->findAll();
or
$crit = new CDbCriteria();
$crit->alias = 'g';
$crit->addColumnCondition(array('g.name'=>'group_1'));
User::model()->with(array('group'=>$crit))->findAll();
or
$crit = new CDbCriteria();
$crit->with = array(
'group'=>array(
'alias'=>'g',
'condition'=>'g.name=:gName',
'params'=>array(':gName'=>'group_1')
)
);
User::model()->findAll($crit);
or
$crit1 = new CDbCriteria();
$crit1->alias = 'g';
$crit1->addColumnCondition(array('g.name'=>'group_1'));
$crit2 = new CDbCriteria();
$crit2->with = array('group'=>$crit1);
User::model()->findAll($crit2);
How i get all users that have a specific group?
select u.* from group g
join user-group ug on g.id = ug.group_id
join users u on u.id = ug.user_id
where g.name = "group_1"