public function actionIndex(){
$activeData = new ActiveDataProvider([
'query' => Student::find()->joinWith('jurusan')->all(),
'pagination' => [
'defaultPageSize' => 12,
]
]);
return $activeData;
}
public function getStudentJurusan()
{
return $this->hasOne(Jurusan::className(), ['jurusan_id' => 'student_jurusan_id']);
}
I have Student and Jurusan which in realted, Student hasOne Jurusan and student jurusa_id is jurusan jurusan_id.I want to get the student * except the student jurusan_id and the jurusan_name in jurusan without the jurusan_id.
If you want to get the specifics columns, you should use query builder provided by Yii2.
http://www.yiiframework.com/doc-2.0/guide-db-query-builder.html
hope this answer your question.
Relation name in 'query' is wrong.
It should be:
'query' => Student::find()->joinWith(['studentJurusan']),
Related
I am trying to implement a dropdown filter in Cgridview, The column is from another table.
//model search code
//person table
public function search(){
$criteria=new CDbCriteria;
$criteria->alias='per';
$criteria->compare('LastName',$this->LastName,true);
$criteria->compare('FirstName',$this->FirstName,true);
$criteria->join='right JOIN person_surveys ps ON ps.id = per.P_Id';
}
//relation to person survey
public function relations()
{
return array(
'user' => array(self::BELONGS_TO, 'PersonSurvey', 'P_Id'),
);
}
//person survey table model search
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('person_id',$this->person_id,true);
$criteria->compare('survey_ids',$this->survey_ids,true);
$criteria->join='left JOIN persons ps ON ps.id = per.P_Id';
}
//controller
public function actiongriddisplay(){
$model2=new Persons('search');
if(isset($_GET['ajax'])){
$model2->attributes =$_GET['Persons'];
$this->render('griddisplay',array('model2'=>$model2));
}
else{
$this->render('griddisplay',array('model2'=>$model2));
}
}
//in view file
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' => $model2->Search(),
'filter' => $model2,
'ajaxType'=>'GET',
// 'ajaxUpdate'=>'items',
//'ajaxUrl' =>$this->createUrl('userManagement'),
'columns' => array(
array(
'name' => 'FirstName',
'header'=>'Full Name',
),
array(
'name' => 'user.survey_ids',
'header'=>'Survey ids',
'filter'=>CHtml::activeDropDownList($model2 ,'survey_ids', array('224'=>'224','223'=>'223','225'=>'225')),
'value'=>'isset($data->user->survey_ids)?$data->user->survey_ids:null'
),
I have put the search on, in models. why is the dropdown filter not working?
Why this is not working please help?
This link (http://www.yiiframework.com/wiki/281/searching-and-sorting-by-related-model-in-cgridview/) will solve your problem.
I have two tables: record, user and a junction table record_user. I display the records, which are related to the logged user, using the Active Record.
In the model User I have the following functions:
public function getRecordUsers()
{
return $this->hasMany(RecordUser::className(), ['user_id' => 'id']);
}
public function getRecords()
{
return $this->hasMany(Record::className(), ['id' => 'record_id'])
->via('recordUsers');
}
See: http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#junction-table
In the model RecordSearch I define the query for the Active Data Provider:
public function search($params)
{
// The Object with all records, to which has the user access (the id of the user is in the junction table record_user).
$loggedUserRecords = YiiUser::findOne(Yii::$app->user->identity->id)->records;
// From the object is extracted an array with ids.
$loggedUserRecordsIds = yii\helpers\ArrayHelper::getColumn($loggedUserRecords, 'id');
// The ids are used to filter the Record object.
$query = Record::find()->filterWhere(['id' => $loggedUserRecordsIds]);
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
...
The code works as expected. But I would like to know, if there is a more direct way to display the related records, without the extraction of ids from the object.
I guess RecordSearch has this relations
public function getRecordUsers()
{
return $this->hasMany(RecordUser::className(), ['record_id' => 'id']);
}
public function getUsers()
{
return $this->hasMany(User::className(), ['id' => 'user_id'])
->via('recordUsers');
}
Or
public function getUsers()
{
return $this->hasMany(User::className(), ['id' => 'user_id'])->viaTable('recordUsers', ['record_id' => 'id']);
}
then you should be able to check query something like:
$dataProvider = new ActiveDataProvider([
'query' => Record::find()->joinWith(['users'])->where(['user_id'=> Yii::$app->user->identity->id]),
]);
if i didn't make a mistake.
As suggested by BHoft the fastest and most simple way is probably the following.
Model Record:
public function getRecordUsers()
{
return $this->hasMany(RecordUser::className(), ['record_id' => 'id']);
}
Model RecordSearch:
$dataProvider = new ActiveDataProvider([
'query' => Record::find()->joinWith(['recordUsers'])->where(['user_id'=> Yii::$app->user->identity->id]),
]);
i am using an self-defined func that encapsu findBySql() to return rows .but got the error showed in the title. but if i test to use self-defined func that encapsu find() ,it worked,why?
Here is my action:
public function actionList()
{
$model = new Loan();
$dataProvider = new ActiveDataProvider(
[
'query' => $model->findValid($_GET['type']),//error comes here
'pagination' => [
'pagesize' => '2',
],
]);
return $this->renderPartial('list', ['model' => $model, 'dataProvider' => $dataProvider]);
}
Here is the object loan's findxx function:
public function findValid($type=null)
{
if($type==null){
return static::findBySql("select * from loan where wmstat&1=1 and (wmstat>>2)&1=0")->all();
}else{
return static::findBySql("select * from loan where wmstat&1=1 and (wmstat>>2)&1=0 and origin="."'".$type."'")->all();
}
}
Futher more,can i change the bit operatin using find() and where() and achieve the same effect ?
The error is clear, query expects valid query instance, while you are passing results of query and not the query itself.
Remove ->all() calls in findValid() method and it should work.
P.S. I strongly recommend to refactor your code to better condition.
Official docs:
ActiveDataProvider $query
ActiveQuery
findBySql()
Here is one with basic code example; not using ->all()
$query = User::find();
$dataProvider = new ActiveDataProvider([
'pagination' => ['pageSize' =>5],
'query' => $query,
]);
return $this->render('index', [
'dataProvider' => $dataProvider,
]);
I've got the model class Contactindiv with relations and search as follows.
public function relations()
{
return array(
'contactlogs' => array(self::HAS_MANY, 'Contactlog', 'ContactIndivID'),
);
}
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('ContactIndivID',$this->ContactIndivID);
$criteria->compare('PersonalTitle',$this->PersonalTitle,true);
$criteria->compare('NameLast',$this->NameLast,true);
$criteria->compare('NameMiddle',$this->NameMiddle,true);
$criteria->compare('NameFirst',$this->NameFirst,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
The current page shows the data in a searchable CGridView format.
My goal is to combine the 'contactlogs' from relations into the Model in order to have it show up on the page in a searchable fashion in the GridView. Basically add a searchable GridView column for each contact showing their contact log.
Thanks ahead of time for your help!
For your first goal (show contactlogs in model) you can write a getter in your main model. It depends, what you want to show in your gridview column but you could use something like:
public function getContacts()
{
$names = array();
foreach($this->contactlogs as $log)
$names[] = $log->name;
return implode(', ', $names);
}
Now you can use contacts as if it where a regular attribute of your "Contactindiv" model.
For your second goal you could add a public property which will contain the filter value, and which you can use in your search() method:
public $contactFilter;
public function search()
{
// ...
if(!empty($this->contactFilter)) {
$criteria->with = array(
'contactlogs' => array(
'joinType' => 'INNER JOIN',
'on' => 'contactlogs.name = :name',
),
);
$criteria->params[':name'] = $this->contactFilter;
}
// ..
}
Now you only need to add all the above in your gridview's columns configuration:
array(
'name' => 'contacts',
'filter' => CHtml::activeTextField($model, 'contactFilter'),
)
Please note, that i'm writing most of this from the top of my head and couldn't fully test it. But it should hopefully make the basic concept clear to you. Please let me know if it works.
Agent:
agent_id (primary key)
User:
f_id (foreign key)
type
I have created relation in this way
public function relations() {
return array(
'user' => array(self::HAS_ONE, 'Users', 'f_id'),
);
}
But I want to add more conditions like join only if type=3 in User table.
thanks.
There is no error like 'Property "CHasOneRelation.0" is not defined' if you use this:
public function relations()
{
return array(
'user' => array(
self::HAS_ONE,
'Users',
'f_id',
'on' => 'user.ref_type = :type',
'params' => array(':type' => 3))
);
}
See this link: http://www.yiiframework.com/forum/index.php/topic/10185-using-relations-and-conditions/
add the condition on your relation
public function relations() {
return array(
'user' => array(self::HAS_ONE, 'Users', 'f_id', array(
'condition' => 'user.type = :type',
'params' => array(':type'=>3)
)),
);
}
http://www.yiiframework.com/doc/guide/1.1/en/database.arr#relational-query-options
You should create a function to get user rather use lazy-load which would use more query even you do not use this relation.
public function getUser(){
return Users::model()->find(array(
'condition'=>'type = :type',
'params' => array(':type'=>3)
));
}
By using this you could use cache function to cache query that relation does not support.
public function getUser(){
return Users::model()->cache(1000)->find(array(
'condition'=>'type = :type',
'params' => array(':type'=>3)
));
}