I have simple CGridView, which is not showing me any data at all.
I've logged query built by CDbCriteria and there was some LIKE conditions which uses mysql default field values, so MySQL searches for entries with default values in required fields.
Since I have none entries matching this condidion it returns 0 rows. But the thing is, I don't need these LIKEs. Is there a way to disable it?
Here's the view:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' => $model->search(),
'filter' => $model,
'columns' => array(
array(
'name' => 'name',
'type' => 'raw',
'value' => 'CHtml::encode($data->name)'
),
array(
'name' => 'email',
'type' => 'raw',
'value' => 'CHtml::link(CHtml::encode($data->email), "mailto:".CHtml::encode($data->email))',
),
),
));
Controller:
public function actionUsers() {
$model = new Users();
$this->renderPartial('users',array(
'model' => $model,
));
}
Function Search of model Users:
return new CActiveDataProvider(get_class($this), array(
'criteria'=>$criteria,
'sort'=>array(
'defaultOrder'=>'user ASC',
),
'pagination'=>array(
'pageSize'=>5
),
));
And Logged Query:
SELECT * FROM `users` `t` WHERE (((((email LIKE :ycp0) AND (`group` LIKE :ycp1)) AND (gender LIKE :ycp2)) AND (city LIKE :ycp3)) AND (name LIKE :ycp4)) AND (av_url LIKE :ycp5) ORDER BY `t`.`name` LIMIT 5. Bound with :ycp0='%NotSet%', :ycp1='%3%', :ycp2='%Secret%', :ycp3='%NotSet%', :ycp4='%NotSet%', :ycp5='%noav.jpg%'
I am new to Stackoverflow and don't have sufficient reputation to post a comment, otherwise I would have asked that you share more information on how you configure your CDbCriteria object in your $model->search() function.
But, I suspect that you are using partial matches in the compare method, which can be disabled by passing false in the $partialMatch parameter as follows:
$criteria = new CDbCriteria;
$criteria->compare('email', $someValue, false);
Or, since false is the default value, you can simple write:
$criteria->compare('email', $someValue);
Related
i was looking for a previous answer, but the ones i've found are related to older cakephp versions
i have two tables, 'magazines' and 'issues' where there is a relation 'issues' BelongsTo 'magazines', this is what IssuesTable looks like:
public function initialize(array $config){
$this->belongsTo('Magazines', [
'foreignKey' => 'id'
]);
}
table magazines has two fields, magazines.id and magazines.name
table issues has two fields, issues.id, issues.magazine_id where issues.magazine_id is the foreign key
to populate a select input in the issues view with the magazine.name values and save the issues.magazine_id, i've set the controller like this
$this->set('magazines', $this->Issue->Magazine->find('list'));
then i've added the following code to the issue view add.cpt
<?php
echo $this->Form->input('name', [
'type' => 'select',
'multiple' => false,
'options' => $magazines,
'empty' => true]);
?>
but i get the input select with the issues.magazine_id as values instead of magazines.name
thanks for your help and comments
You want to use find('list') as this will return the primary key and display field:-
$this->set(
'magazines',
$this->Issues->Magazines->find('list')
);
Then in your form you need the input name to be magazine_id if you're wanting to set the foreign key for the association:-
echo $this->Form->input(
'magazine_id',
[
'type' => 'select',
'multiple' => false,
'options' => $magazines,
'empty' => true
]
);
See the docs for more info.
Update
If you're experiencing issues with find('list') it is perhaps because your model's displayField is not getting set correctly. Cake normally determines the displayField for the model on initialisation. If this isn't working, or you want a different field you can set this manually in the model's initialize() method. E.g.:-
class MagazinesTable extends Table
{
public function initialize(array $config)
{
$this->displayField('name');
}
}
Changing 'name' to the appropriate field.
Alternatively, you can choose which field Cake will use for the values returned by find('list') (this is particularly useful when you want to override the default displayField). E.g.:-
$this->Issues->Magazines->find('list', [
'keyField' => 'id',
'valueField' => 'name'
]);
Display selected option in month helper
$this->Form->month('students.month', [
'label' => false,
'value'=>date('m'),
'required'=>true
]);
This actually helped me.
$this->Issues->Magazines->find('list', [
'keyField' => 'id',
'valueField' => 'name'
]);
In my GridView I want to display all records of my table 'reply'. The table has relations to the tables 'author' and 'task' and not every reply has a task.
The table 'task' has a relation with another table called 'concern'.
Here ist the relations() of my model Reply:
public function relations() {
return array(
'trak' => array(self::HAS_MANY, 'Task', 'reply_id', 'condition' => 'task.deleted<>1'),
'author' => array(self::BELONGS_TO, 'Author', 'author_id'),
);
}
The search() method of my model Reply has the following code:
public function search() {
$criteria = new CDbCriteria;
$criteria->with = array(
'author' => array('select' => 'id, name, role, office_id, abk', 'together' => false),
'author.office' => array('select' => 'id, name'),
'task' => array('select' => 'id, concern_id', 'together' => true),
'task.concern' => array('select' => 'id, classification_id', 'alias' => 'concern'),
);
$criteria->compare('t.id', $this->id);
$criteria->compare('t.create_time', $this->create_time);
$criteria->compare('t.create_date', $this->create_date, true);
$criteria->compare('t.office.id', $this->search_office);
$criteria->compare('t.author_id', $this->author_id);
$criteria->compare('t.rel', $this->rel, true);
$criteria->compare('t.author_id', $this->author_id);
$criteria->compare('t.lektor_id', $this->lektor_id);
$criteria->compare('t.issue_id', $this->issue_id);
$criteria->compare('t.reply_text', $this->reply_text, true);
$criteria->compare('t.deleted', $this->deleted);
if (EWMParam::getValue(EWMParam::MODUL_SCHLAGWORTE))
$criteria->compare('t.tags', $this->tags, true);
$criteria->compare('t.text_name', $this->text_name, true);
$criteria->compare('t.use_count', $this->use_count);
$criteria->compare('concern.classification_id', $this->classification_id);
$criteria->compare('t.update_time', $this->update_time);
$criteria->compare('t.update_user', $this->update_user);
$criteria->compare('t.global', $this->global);
if (EWMParam::getValue(EWMParam::MODUL_confirmationN))
$criteria->compare('t.confirmation', $this->confirmation);
$criteria->compare('t.confirmation_text', $this->confirmation_text, true);
$criteria->compare('t.use', $this->use, true);
$pagination = EWMPageSortFilterHelper::getPagination($this);
$sort = new CSort();
$sort->defaultOrder = 't.id DESC';
$sort->attributes = array(
'global' => 't.global',
'search_office' => 'office.name',
'id' => 't.id',
'text_name' => 't.text_name',
'confirmation' => 't.confirmation',
'author_id' => 'author.name',
'create_date' => 't.create_date',
'tags' => 't.tags',
'use' => 't.use',
'classification_id' => 'classification_id',
);
$sort->applyOrder($criteria);
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
'pagination' => $pagination,
'sort' => $sort
));
}
In my GridVew only replys with a task are displayed and all filters work fine. But I want to display all replys with a task and all replys without a task. If I
delete in the search() method in the array for $criteria->with the elements 'task' and 'task.concern' all replys are displyed. But the filter for the row
'Classifcation' which comes from the relation 'task.concern' doesn't work. Logically I get the error "Column not found: 1054 Unknown column 'concern.classification_id' in 'where clause'".
Is it possible to display all replys and to filter those replys by the classification? Do you have an idea?
You should look into how Yii relations work.
One thing that comes into my mind is that when adding the relations in the with() property the SQL generated might include INNER JOINs.
That's why when having the relations included you're not getting any reply without tasks.
In order to fix that you should make sure that the SQL generated is using LEFT JOINs.
You can do that by using joinType property of a relation:
http://www.yiiframework.com/doc/api/1.1/CActiveRelation#joinType-detail
And you could specify LEFT JOIN there.
'task' => array('select' => 'id, concern_id', 'together' => true, 'joinType'=>'LEFT JOIN'),
'task.concern' => array('select' => 'id, classification_id', 'alias' => 'concern', 'together' => true, 'joinType'=>'LEFT JOIN'),
That might do the trick. But maybe you need some more tweaking if it is not working just as expected.
If you want to debug what is actually happening, you could put a bad field/table name inside the criteria that would result in a database error and then you can look in the SQL code that was executed and see how tables are joined.
Suggested links:
http://www.yiiframework.com/doc/guide/1.1/en/database.arr
http://www.yiiframework.com/wiki/527/relational-query-lazy-loading-and-eager-loading-with-and-together/
http://www.yiiframework.com/wiki/428/drills-search-by-a-has_many-relation
[EDIT]
There are just some js code that I used for sorting that disables the selection the div container.
I am using the Yii cgridview to show my data. But I cannot type into the input text field and cannot select from the select/dropdown, these are the filter options on the cgridview. By the way, the data is from a view, not a from a regular table.
Below are codes on my controller,
$request = new Request;
$request->unsetAttributes();
if(isset($_GET['Request'])
$request->attributes=$_GET['Request'];
$this->render('index', array(
'request' => $request,
));
Below are the safe fields on the model,
array('request_id, facility_id, client_id, status, description, submitted_by, submitted, acknowledge, req_type', 'safe')
Below are the codes on the model search method
function setRequests(){
$criteria = new CDbCriteria;
$criteria->compare('req_type',$this->req_type, true);
$criteria->compare('description', $this->description, true);
$criteria->compare('status', $this->status, true);
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
'pagination'=>array('pageSize'=>5),
));
}
Below are the codes on the view file.
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'request-clist',
'dataProvider'=>$request->setRequests(),
'filter'=>$request,
'columns'=>
array(
array('name'=>'req_type',
'header'=>'Item',
'value'=>'CHtml::link($data->req_type, array($data->url));',
'type'=>'raw',
'filter' => CHtml::dropDownList('Request[req_type]',
$request->req_type,
array(
'Notice' => 'Notice',
'FAR' => 'FAR',
'PC' => 'PC',
'EM'=>'EM',
'RH'=>'RH'),
array('empty' => '(Select)'))
),
array('name'=>'description',
'header'=>'Description',
'filter'=>CHtml::textField('Request[description]',$request->description)),
array('name'=>'status',
'header'=>'Status',
'filter'=>CHtml::textField('Request[status]',$request->status)),
),
));
Are there some things I miss?
How can I create a search form/criteria for "one-to many" relations: let's say "select all teams with crowd > 10.000".
I'm using MongoRecord extension (http://www.yiiframework.com/extension/mongorecord/) as a basic active record for MongoDb.
I created a GridView with Yii based on a collection from a mongo db (it works for me).
One of my document`s collection has a structure like this:
{
_id":1,
"teamId":2453,
"teamName":"Team A",
"competition":["Competition A","Competition B"],
"matches":
[
{
"_id":147852,
"crowd":10234,
"yellowCards":2,
"scorers" [{....}]
....
}
]
...
}
My documents:
$teams = MongoTeam::model()->findAll();
My dataProvider is:
$dataProvider=new CArrayDataProvider($teams, array(
'id'=>'_id',
'sort'=>array(
'attributes'=>array(
'_id', 'teamId', 'teamName', 'matches', ...
),
),
'pagination'=>array(
'pageSize'=>20,
),
));
$this->render('index', array('dataProvider'=>$dataProvider));
And in the view I have something like this:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns'=>array(
array(
'name' => 'Team ID',
'type' => 'raw',
'value' => 'CHtml::encode($data->teamID)'
),
array(
'name' => 'Team Name',
'type' => 'raw',
'value' => 'CHtml::encode($data->teamName)'
),
...
But I'm not able to create filters with criteria for subdocuments (my case: "matches"). I don't want to use any other mongoDB extension/module etc.
Thanks and sorry for my bad english.
$query=array(
'matches.crowd'=>array('$gt'=>10000),
'matches.$'=>1
);
$teams = MongoTeam::model()->findAll($query);
You can use like this. But you must not use a data provider like that. Because it will generate too much rows into the $teams var. You must use criteria for data providers. I am doing that with YiiMongoDbSuite it has EMongoCriteria and EMongoDataProvider classes to accomplish that.
Suppose I have model User which have many to many relation to itself named as friends.
so $user->friends (or $model->friends in view) gives me an array of User objects. I wanted to display the friends as gridview. But CGridView data as dataProvider object. Googling for it found the way to convert array of model objects to dataProvider object as given below.
$this->widget('zii.widgets.grid.CGridView', array(
'id' => 'gridUser',
'dataProvider' => new CArrayDataProvider($model->friends, array()),
));
Now using this I get an error
Property "User.id" is not defined.
UPDATE
public function relations()
{
return array(
'friends' => array(self::MANY_MANY, 'User', 'friendship(user_id, friend_id)'),
);
}
I use two stage building the provider shown below. But I found that it gives you trouble in terms of Pagination. I have not bothered to resolve that problem since am doing other things
$dataProvider = new CArrayDataProvider('User');
$dataProvider->setData($model->friends);
$this->widget('zii.widgets.grid.CGridView', array(
'id' => 'gridUser',
'dataProvider' =>$dataProvider,
));
That being said, your code should work (see the example below from API docs). I suspect there is wrong attribute in your relations than the provided code. Re-check the relation definition if it is ok
From Yii docs:
$rawData=Yii::app()->db->createCommand('SELECT * FROM tbl_user')->queryAll();
// or using: $rawData=User::model()->findAll(); <--this better represents your question
$dataProvider=new CArrayDataProvider($rawData, array(
'id'=>'user',
'sort'=>array(
'attributes'=>array(
'id', 'username', 'email',
),
),
'pagination'=>array(
'pageSize'=>10,
),
));
Got it :) , i can use CActiveDataProvider instead of CArrayDataProvider as given below
$this->widget('zii.widgets.grid.CGridView', array(
'id' => 'gridUser',
'dataProvider' => new CActiveDataProvider('User', array(
'data'=>$model->friends,
)),
//...... columns display list.....
));
Anyways thanks for the reply #Stefano