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"
Related
I have two models in yii2 which are related . I would like to compare them such that using an id i get the id values in a not in b
That is
I have a pr model and pr items model and i would like to get the id values in pr model not in pritems model
I have tried
$pr = Tblpr::find()->all(); //This returns all pr model items
$pritems = Tblpritems::find()->all() //this returns all pritems
$pr and $pritems are related by id such that id in pritems is a foreign key referencing pr
How can i get the ids in pr but not in pritems.
There are several way
You can try with findBySql (using a subquery )
$sql = 'SELECT * FROM tblpr as a
where a.id not in (select b.id
Tblpritems as b)';
$model = Tblpr::findBySql($sql)->all();
or using left join
$sql = 'SELECT * FROM tblpr
left join Tblpritems on tblpr.id = Tblpritems. id
where wTblpritems.id is null';
$model = Tblpr::findBySql($sql)->all();
Or you can use activeQuery
$query = Tblpr::find();
$query->leftJoinWith('tblpritems', 'tblpr.id = tblpritems.id');
$query->andWhere(['pritems.id' => null]);
$model = $query->all();
for dataProviding you can
$provider = new ActiveDataProvider([
'query' => $sql,
'pagination' => [
'pageSize' => 20,
],
]);
Just join relatated table and check it ids for null:
$query = Tblpr::find();
$query->innerJoinWith('tblpritems', false);
$query->andWhere(['pritemsId' => null]);
$prWithOutItems = $query->all();
It's better to extend it to TblprQuery and use like Tblpr::find()->withoutItems()->all().
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);
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.
First I will give an example with some pseudo code and then I will explain what is the problem. Let me say I have two entities User and Phonenumber. Their relation is one-to-many. In my UserRepository I can have something like that:
class UserRepository
{
public function getUser($id, $type)
{
$users = $this->createQuery("SELECT u, p FROM User u JOIN u.phonenumbers p
WHERE u.id = :id AND p.type = :type")
->setParameters(array(
'id' => $id,
'type' => $type,
))
->getResult();
return $users[0];
}
}
In my app if I have something like:
$user = $userRepo->getUser(1, 'home');
var_dump($user->getPhonenumbers()); // here phonenumbers collection is ok
$user = $userRepo->getUser(1, 'work');
var_dump($user->getPhonenumbers()); // Here phonenumbers collection is wrong.
// It's exactly the same as the previous one.
So my questions is: Is it possible to use fetch join (with different criteria) and to get the proper collection each time?
Fetch joining and filtering a collection are not things that work together quite well. Here's how you should do it:
SELECT
u, p
FROM
User u
JOIN
u.phonenumbers p
JOIN
u.phonenumbers p2
WHERE
u.id = :id
AND
p2.type = :type
This applies filtering on the second joined (and not hydrated) p2, which results in correct hydration and filtering.
Use querybuilder, it is much simpler.
public function getUser($id, $type)
{
return $this->createQueryBuilder("u")
->leftJoin("u.Phonenumbers", "p", "WITH", "p.type=:type")
->where("u.id=:id")
->setParameters(.....)
->getQuery()
->getOneOrNullResult() ;
}
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.