$criteria->select = 't.*,count(business_unit.id) as TotalBusinessUnits,count(users.id) as TotalUsers ,count(positions.id) as TotalPositions, count(skills.id) as TotalSkills , users.first_name , users.last_name, count(question_bank.id) as TotalQuestions';
$criteria->condition = "`t`.status = '1'";
$criteria->group = 't.id';
$criteria->order = 'created DESC';
$criteria->join = " inner join users on users.company_id = `t`.id";
$criteria->join .= " left join business_unit on business_unit.company_id = `t`.id";
$criteria->join .= " left join billingdetails on billingdetails.company_id = `t`.id";
$criteria->join .= " left join positions on positions.company_id = `t`.id";
$criteria->join .= " left join skills on skills.company_id = `t`.id";
$criteria->join .= " left join question_bank on question_bank.company_id = `t`.id";
It works fine and get all columns which I select.
But when I pass it in CActiveDataProvider it gets only this attributes.
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'pagination' => $pages
));
How I select all columns?
In Yii if you are using as for sql, it needs a public variable to store the value in.
add all your custom column names as public variables on the model and all should be dandy.
so if you have $criteria->select = 't.*,count(business_unit.id) as TotalBusinessUnits, this will create the corresponding sql . but Yii does not recognise TotalBusinessUnits as a valid column on the table.
So if you add public $TotalBusinessUnits; in your model Yii has a place to store this value.
Also you should then add TotalBusinessUnits to your safe attributes rule so that Yii knows it safe to fetch.
public $TotalBusinessUnits;
public function rules(){
return array(
// your rules
array('TotalBusinessUnits','safe'),
);
}
public function search(){
$criteria->select = 't.*,count(business_unit.id) as TotalBusinessUnits';
// your criteria
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}
Related
Is it possible to write sub queries with Yii active record?
I need to add a subquery in the FROM clause. Below is the SQL with the subquery but I want to specifically write it using Active Record.
In SQL, Policy has a many to many relationship with policy_vehicles.
SQL Query:
select * from (SELECT Name , GROUP_CONCAT(PV.VehicleId SEPARATOR ',') as VehicleIds
FROM `policies` `t`
LEFT JOIN policy_vehicles PV USING(PolicyId)
WHERE (Type IN ('C', 'E')) AND (Status='Active')
GROUP BY t.PolicyId
) k where VehicleIds like '%1%' AND VehicleIds like '%2%'
This is how I want to use it in the Controller class:
$model = Policy::model();
$model->Status = array('Active');
$model->VehicleIds = array(1,2);
$model->Type = array('C', 'E');
$datas = $model->search()->getData();
print_r($datas);
Search function in the model:
public function search() {
$joins = array();
$criteria = new CDbCriteria;
$criteria->compare('Type', $this->Type);
$criteria->compare('Status', $this->Status);
array_push($joins, 'LEFT JOIN policy_vehicles PV USING(PolicyId)');
$criteria->join = implode(' ', $joins);
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}
I have a CDBCriteria here:
$criteria = new CDbCriteria;
$criteria->select = array('t.lastname', 't.name', 't.patronomic', 't.dob', 'n.nationality', 't.token', 'm.status');
$criteria->join = 'LEFT JOIN hrp_nationalities n ON (n.id = t.nationality_id) ';
$criteria->join .= 'LEFT JOIN hrp_marital_status m ON m.id = t.marital_status_id';
$criteria->condition = "t.`alive` = 1 AND t.`org_id` = ".$_SESSION['org_id'];
$criteria->order = 't.id DESC';
My question is why m.status and n.nationality are not retrieved into the resulting object?
If you are using the CDbCriteria on a model class eg $results = User::model()->findAll($criteria); then the result will contain only fields from user table, not the relations'. The reason is that when the resultant model objects are created there is no field declared for the relation columns in the model.. So you need to create fields in the model..
in your case nationality, status
Just write in your model
public $nationality;
public $status;
And if your model also has a field named status, use an alias for the relation's field status..
public $m_status;
$criteria->select = array('t.lastname', 't.name', 't.patronomic', 't.dob', 'n.nationality', 't.token', 'm.status as m_status');
I just remember I have answered an old similar question.. Read answer here: https://stackoverflow.com/a/11594530/1114536
I have 3 tables:
bank
bank_details
bank_bank_details
Relation between them:
bank model:
public function relations() {
return array(
'bankBankDetails' => array(self::HAS_MANY, 'BankBankDetails', 'bank_id'),
);
}
bank_details model:
public function relations() {
return array(
'bankBankDetails' => array(self::HAS_MANY, 'BankBankDetails', 'bank_details_id'),
);
}
bank_bank_details model:
public function relations()
{
return array(
'bank' => array(self::BELONGS_TO, 'Bank', 'bank_id'),
'bankDetails' => array(self::BELONGS_TO, 'BankDetails', 'bank_details_id'),
);
}
I want to fetch bank details like bank_name, ifsc etc info in admin view of bank_details model.
The normal SQL query I have generated which works perfectly fine:
SELECT b.name
FROM bank b
LEFT JOIN bank_bank_details bbd ON bbd.bank_id = b.bank_id
LEFT JOIN bank_details bd ON bd.bank_details_id = bbd.bank_details_id
WHERE bd.bank_details_id = bbd.bank_details_id
LIMIT 0 , 30
Now I just wants to integrate this with Yii CDBCriteria but its not working for me. Please check the code below:
public function search() {
$criteria = new CDbCriteria;
// select b.name
// from bank b
// left join bank_bank_details bbd
// on bbd.bank_id = b.bank_id
// left join bank_details bd on bd.bank_details_id = bbd.bank_details_id
// WHERE bd.bank_details_id = bbd . bank_details_id;
$criteria->compare('bank_details_id', $this->bank_details_id);
$criteria->compare('first_holder_name', $this->first_holder_name, true);
$criteria->compare('nominee1', $this->nominee1, true);
$criteria->select = 'b.name';
$criteria->join = 'LEFT JOIN bank_bank_details bbd ON bbd.bank_id = b.bank_id ';
$criteria->join .= 'LEFT JOIN bank_details bd ON bd.bank_details_id = bbd.bank_details_id';
$criteria->condition = 'bd.bank_details_id = bbd.bank_details_id';
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
'pagination' => array(
'pageSize' => 10,
),
));
}
Error:
Error 500 Found
CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'b.bank_id' in 'on clause'
Any help would be appreciated.
You need to set alias to your table like this:
$criteria->alias='b'; or use default alias "t" instead of "b"
read more at
http://www.yiiframework.com/doc/api/1.1/CDbCriteria#alias-detail
Try:
public function search() {
$criteria = new CDbCriteria;
$criteria->compare('bank_details_id', $this->bank_details_id);
$criteria->compare('first_holder_name', $this->first_holder_name, true);
$criteria->compare('nominee1', $this->nominee1, true);
$criteria->select = 'bank.name';
$criteria->with = array(
'bankBankDetails' => array('joinType'=>'LEFT JOIN'),
'bankBankDetails.bank' => array('joinType'=>'LEFT JOIN'),
);
$criteria->addCondition('t.bank_details_id = bankBankDetails.bank_details_id');
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
'pagination' => array(
'pageSize' => 10,
),
));
}
Main table (which is in FROM) has alias t and after compare you already having some condition, than you need to add to existing, not rewrite
UPDATE
If you do query from model bank_details then the main table (in FROM) must be bank_details. Query will be:
SELECT b.name
FROM bank_details bd
LEFT JOIN bank_bank_details bbd ON bd.bank_details_id = bbd.bank_details_id
LEFT JOIN bank b bbd ON bbd.bank_id = b.bank_id
WHERE bd.bank_details_id = bbd.bank_details_id
LIMIT 0 , 30
here
$criteria->select = 'b.name';
You are selecting only bank name and no id is selected
Not sure with the yii format something like
$criteria->select = 'b.name,b.bank_id';
or
$criteria->select = array('b.name,b.bank_id');
As #Evgeniy mentioned, you will need to set the alias using $criteria->alias = 'b';
http://www.yiiframework.com/doc/api/1.1/CDbCriteria#alias-detail
You might also want to look into using CDbCriteria::with you can use this to select related models.
http://www.yiiframework.com/doc/api/1.1/CDbCriteria#with-detail
If you use the above, make sure you also use CDbCriteria::together correctly. To select all related models at once, set it to true;
http://www.yiiframework.com/doc/api/1.1/CDbCriteria#together-detail
problem : CDbCriteria print out wrong result.
This is the model search function.
public function summary()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->select = 't.*';
if (Yii::app()->user->checkAccess('Reviewer')):
$criteria->addSearchCondition('t.reviewers',Yii::app()->user->id,false, 'AND');
endif;
if (Yii::app()->user->checkAccess('Implementer')):
$criteria->addSearchCondition('t.implementers',Yii::app()->user->id,false, 'OR');
endif;
if (Yii::app()->user->checkAccess('Creator')):
$criteria->compare('t.creator',Yii::app()->user->id, false, 'OR');
endif;
$criteria->compare('request_type_id',$this->request_type_id);
$criteria->compare('request_category_id',$this->request_category_id);
$criteria->compare('financial_type_id',$this->financial_type_id);
$criteria->compare('urgency_id',$this->urgency_id);
$criteria->compare('eta_date',$this->eta_date,true);
if (Yii::app()->user->checkAccess('Reviewer') || Yii::app()->user->checkAccess('Implementer')):
$criteria->join = "JOIN profiles p ON (p.user_id = t.creator)";
if($this->creator):
$criteria->addSearchCondition('p.firstname',$this->creator, true, 'AND');
endif;
endif;
if(isset($this->status)):
$criteria->compare('t.status',$this->status);
endif;
$data = new CActiveDataProvider(get_class($this), array(
'criteria'=>$criteria,
'pagination'=>false,
));
$_SESSION['all'] = $data;
$data = new CActiveDataProvider(get_class($this), array(
'pagination'=>array('pageSize'=> Yii::app()->user->getState('pageSize',
Yii::app()->params['defaultPageSize']),),
'criteria'=>$criteria,
));
$_SESSION['limited'] = $data;
return $data;
}
above code was print out the query when I trace with CWebLogRoute but there are no record.
Querying SQL: SELECT t.* FROM request t JOIN profiles p ON
(p.user_id = t.creator) WHERE t.reviewers LIKE :ycp1 LIMIT 10
When I change those query to following one, it was print out the records.
SELECT t.* FROM request t JOIN profiles p ON ( p.user_id =
t.creator ) WHERE t.reviewers LIKE '%3%' LIMIT 0 , 30
How can I solve the problem?
Try change
$criteria->addSearchCondition('t.reviewers',Yii::app()->user->id,false, 'AND');
to
$criteria->addSearchCondition('t.reviewers',Yii::app()->user->id, true, 'AND');
Also check format of reviewers and how it write down in the records: it's maybe record as ' 3', '3 ', or ' 3 '.
It's have to update records by update request set reviewers = trim(reviewers)
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.