Yii cgridview using dynamic active record model - yii

I'm using the Yii-dynamic-active-record model class to get and put data to various database tables. Now I'd like to use cgridview to quickly build some views of this data, but I'm getting hung-up on writing a search function for this class.
I know that I could always do a foreach loop within the view and make my own html table, but if I could get the Yii way working that would be great for DRY.
*All the db tables have a ID column and this is the only column that really needs to be displayed... if you could get all the columns that would just be bonus points.
Thanks :)
Model
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('ID',$this->ID);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
View
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'entry-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'ID',
),
));
Controller
$tablename=$_GET['tname'];
$table=Entry::forTable($tablename);
$model=$table->findAll();
if(isset($_GET['Entry']))
$model->attributes=$_GET['Entry'];
$this->render('all',array(
'model'=>$model,
));

I am a little confused by what you have done here, however I think I have a solution. First off, in line 3 of your controller code, you call $model = $table->findAll(); this is likely not what you intended, as it will provide you with an ActiveRecord[]. What you want to do is to pass your $table into the gridview. So your controller code would look like this:
$tablename=$_GET['tname'];
$model=Entry::forTable($tablename);
if(isset($_GET['Entry']))
$model->attributes=$_GET['Entry'];
$this->render('all',array(
'model'=>$model,
));
you then need to pass in the table name to the CActiveDataProvider in your model:
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('ID',$this->ID);
return new CActiveDataProvider($this->tableName(), array(
'criteria'=>$criteria,
));
}
now for the "yucky" part, you need to edit the static model method of CActiveRecord to this:
if(isset(self::$_models[$className]))
return self::$_models[$className];
else
{
if(class_exists($className)){
$model=self::$_models[$className]=new $className(null);
$model->_md=new CActiveRecordMetaData($model);
$model->attachBehaviors($model->behaviors());
}
else{
$model = Entry::forTable($className);
}
return $model;
}
This tells it to load from the Entry table when a class of that name does not exist. This practice is discouraged, however its the only way I see of getting around your issue.

Related

Modelname and its behaviors do not have a method or closure named "getData". in yii

i dont know where am i going wrong i did play round with it but did not achieve anything.
i wanna display data using cListview but unable to do so
i have a function in model
Model
public function psearch1()
{
$name=$_GET['search'];
$criteria=new CDbCriteria;
$criteria->alias="t";
$criteria->select="t.id,t.name,t.model";
$criteria->condition='name LIKE "%'.$name.'%"';
return new CActiveDataProvider($this,array('criteria'=>$criteria,));
}
controller
public function actionPsearchindex()
{
$dataProvider=new Modelname('psearch');
$this->render('psearchindex',array(
'dataProvider'=>$dataProvider,
));
}
view
psearchindex
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_psearchindex1',
));
_psearchindex
echo CHtml::encode($data->name);
when i execute i get the following
error
Modelname and its behaviors do not have a method or closure named "getData".
this is my first attempt am doing so but unable to figure out whats wrong
a new model is not a data provider, call your custom search on it
public function actionPsearchindex()
{
//$dataProvider=new Modelname('psearch');// a new model is not a data provider
$model = new Modelname('psearch');
$this->render('psearchindex',array(
'dataProvider'=>$model->psearch1(), // this will give you a data provider that you can use
));
}

Yii – “Model.id” not defined for CArrayDataProvider and CSqlDataProvider - keyfield

In my controller I want to display all the users of an application so I have used this code:
public function actionClientu($id)
{
$model=$this->loadModel($id);
$appUsers= $model->users;
$dataProvider=new CArrayDataProvider($appUsers);
$this->render('clientu',array(
'dataProvider'=>$dataProvider,
));
}
but I have this error:
"Undefined AppUser.id"
it refer to this line:
$dataProvider=new CActiveDataProvider('AppUser', $appUsers);
Any help please ?
I solved my problem ! here is the cause of the problem:
my model keyfield isn't named id and I haven’t defined which column should be used.
So I just have to set the keyField like this:
new CArrayDataProvider($users, array('keyField' => 'user_id'));
new CSqlDataProvider($users, array('keyField' => 'user_id'));

Two Different Search Functions

I have two search functions. One for public and one for admin search. They are exactly the same:
public function search()
{
// #todo Please modify the following code to remove attributes that should not be searched.
$criteria=new CDbCriteria;
//$criteria->compare('ID',$this->ID);
$criteria->compare('t.IDkorisnik',Yii::app()->user->getId());
$criteria->compare('start_time',$this->start_time,true);
$criteria->compare('end_time',$this->end_time,true);
//$criteria->compare('information',$this->information,true);
$criteria->compare('country',$this->country,true);
$criteria->compare('city',$this->city,true);
$criteria->compare('start_price',$this->start_price);
$criteria->compare('min_bid',$this->min_bid);
$criteria->compare('valuta',$this->valuta,true);
$criteria->compare('title',$this->title,true);
$criteria->with=array('relationIDuzgajivac','relationIDgolub');
$criteria->compare('username',$this->uzgajivacSearch);
$criteria->compare('brojgoluba',$this->golub_search, true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'pagination'=>array('pageSize'=>50),
));
}
except in search() I have this
$criteria->compare('t.IDkorisnik',Yii::app()->user->getId());
in publichsearch() I don't.
As you may see there is relation search. when I open admin page it works in publicsearch page it doesn't work, I don't know why
I never realized that when I'm creating new action
public function actionPublicSearch()
{
$model=new Auction('search');
$model->unsetAttributes(); // clear any default values
if(isset($_GET['Auction']))
$model->attributes=$_GET['Auction'];
$this->render('publicsearch',array(
'model'=>$model,
));
}
this $model=new Auction('search'); within model always has to be 'search' not something like 'public_search'
and then within view, where CGridView is created
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'auction-grid',
'dataProvider'=>$model->public_search(),
dataProvider is a place where I put my search function, in this case public_search

Attaching a count variable to an object

I need some help in showing a count of posts of each user in a CGridView.
For example:
I have a User and Post model.
I can access the posts of a user through $user->posts
Is there something I can add to have $user->num_posts
You should simply use a stat relation, e.g. in your User model :
public function relations()
{
return array(
// ...
'posts' => array(self::HAS_MANY, 'Post', 'user_id'),
'num_posts' => array(self::STAT, 'Post', 'user_id'),
// ...
);
}
http://www.yiiframework.com/doc/guide/1.1/fr/database.arr#statistical-query
EDIT :
You should also use eager loading to build your dataprovider, e.g. :
$criteria=new CDbCriteria;
$criteria->with('num_posts');
About SQL queries, this should use only 3 queries :
one query for gridview page count,
one query to get users models,
one query to get users num_posts.
Just take a look at Yii logs to be sure.
You can use getter in your Post model.
Something like this:
public static function getpostscount($id)
{
$total=0;
$provider=Post::model()->findall('user_id=:user_id',array(':user_id'=>$id));
foreach ($provider as $data)
{
if ($data->userid==$id)//userid name of column with user id in post model
{$total++;
}
}
return $total;
}
Then in your view just pass user->id to getter and it will return you count of posts for this user. Something like this:
echo "User have".Post::model()->getpostscount($user->id);//$user->id is id of user for wich we will look count of posts
Regards.

searching and filtering in yii

How to filter the search results as a combination of checkboxes and dropdown in Yii? I have some categories as checkboxes and budget as dropdown that is listing from database. WIth multiple checkboxes checked and selecting a value from dropdown, how can I filter out the search results.. Is there any better way ?? (My requirement is like in this link. http://www.ebay.in/sch/i.html?_from=R40&_sacat=0&_nkw=pendrives&rt=nc&LH_FS=1 )
I recommend to use a search model. This could look like this:
class SearchProducts extends CFormModel
{
public $minPrice;
public $maxPrice;
public $categories;
// Add a public property for each search form element here
public function rules()
{
return array(
// You should validate your search parameters here
array('minPrice,maxPrice,categories', 'safe'),
);
}
public function search()
{
$criteria = new CDbCriteria;
if(!empty($this->minPrice))
$criteria->addCondition('price > '.(int)$this->minPrice);
if(!empty($this->maxPrice))
$criteria->addCondition('price < '.(int)$this->maxPrice);
if(!empty($this->categories))
$criteria->addInCondition('category_id', $this->categories);
// Add more conditions for each property here
return new CActiveDataProvider('Product', array(
'criteria' => $criteria,
// more options here, e.g. sorting, pagination, ...
));
}
}
In your controller you create a new instance of the search form and assign search variables as usual:
public function actionProducts()
{
$searchModel = new ProductSearch();
if(isset($_POST['ProductSearch']))
$searchModel->attributes = $_POST['ProductSearch'];
$this->render('products', array(
'searchModel' => $searchModel,
));
}
Finally in your view you can now render
A regular Yii form for $searchModel properties which will be your search filter form
A CListView or a CGridView where you set the provider to $searchModel->search() which will be your search results.
For the checkboxes you'd use a checkBoxList:
<?php $this->formCheckBoxList($model, 'categories[]', Category::opts()) ?>
Note the [] which indicates that this should be posted as array. For convenience i usually also implement a static opts() method in some models, which returns a list of id=>name that you can use for dropDownList or checkBoxList options.
This is only the basic pattern. You can easily extend it to create really powerful search forms and result list. Just always keep in mind that you should keep all search related data in another model.
try this extension: ddautofilter
https://bitbucket.org/jwerner/yii-ddautofilter/overview