in cgridview there are a blank field to filter the data above every column how can I filter data depend on multi comparison creteria for example I can put >5 in this field in ID column to filter the data to be only records from id 6 and above.
I want to put something like >5 and <10 how can I do that
You create $filter instance of YourModel and implement custom search() method like its shown here:
Controller:
public function actionIndex() {
$filter = new YourModel('search');
$filter->unsetAttributes();
if (isset($_GET['YourModel']))
$filter->attributes = $_GET['YourModel'];
$this->render('yourview', array(
'filter' => $filter,
));
}
View:
<?php $this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' => $filter->search(),
'filter' => $filter
...
));
As the result, attributes of $filter model contain values that user put in filter input fields of CGridView and its search() method can parse and use these values in any way to create required CDbCriteria and then return filtered CActiveDataProvider.
I didn't test it but to filter some attribute field of your model one could write something like this:
public function search()
{
$criteria = new CDbCriteria();
$matches = array();
if (preg_match('/^(<|>)(.+)$/', $this->field, $matches))
{
$criteria->addCondition('field ' . $matches[1] . ' :field');
$criteria->params[':field'] = $matches[2];
}
else
{
$criteria->addCondition('field = :field');
$criteria->params[':field'] = $this->field;
}
// TODO: add conditions for other fields
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}
If you want to have both < and > conditions in one filter field it's up to you to decide which format to use and how to parse it to prepare search criteria.
In my case i use this code:
$matches=array();
if(preg_match('/(.+)(\s)(.+)/',$this->field,$matches)) {
$criteria->addCondition("field ".$matches[1]." and field ".$matches[3]);
} else {
$criteria->compare('field',$this->field);
}
And in filter input in cgridview i can use "<100 >50" (whitespace character is important in this case)
Related
I need to conver this sql statement that has a multi column group by clause into CActiveDataProvider in Yii version 1.1.4?
select * from my_table_name group by bookname,categorytitle,bookkey order by bookname,categorytitle,bookkey asc;
I need a CActiveDataProvider to feed a CGridView search function. Apparently, I only have a simple return in my model of the search function that runs my CGridView
return new CActiveDataProvider(get_class($this),
array(
'criteria' => $criteria,
'sort' => array(
'defaultOrder' => 'id ASC'
),
'pagination' => array('pageSize' => ActiveRecord::PAGE_SIZE),
));
so how to convert the sql statement that I gave into CActiveDataProvider format ?
You can do using two way -
Make sql view and than create yii model and use this in your
controller or page view.
Create custom search function in your existing model and use group by
e.g. -
<?php
public function new_search(){
$criteria = new CDbCriteria();
...
..
$criteria->group = "bookname, categorytitle, bookkey";
$criteria->order = "bookname, categorytitle, bookkey";
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'pagination'=>array('pageSize'=>100)
));
}
?>
I want to hide a column in yii based on a condition. I have used a function in model. but visible functionality is not working in this column.
$this->widget('zii.widgets.grid.CGridview', array(
'id'=>'gridview',
'dataProvider'=>$dp,
'columns'=>array(
array(
'header' => 'Entries',
'value' => '$data->entry_name'
),
array(
'name' => 'value',
'value' => '$data->entry_name',
'visible'=>'$data->show()',
'type'=>'raw'
),
)
)
);
function in Model
public function show()
{
.........
return 1 or 0;
}
but it not working. Please help
I don't see a condition anywhere yet. You should use a comparison operator like return $this->attribute !== null; in your show function. Which returns true if attribute contains some value. Or if you want to do it on random you can return rand(0,1) == 1;.
I have a query as follows
$criteria1 = new CDbCriteria();
$criteria1->condition = 'id = 1';
$modelA=Table1::model()->find($criteria1);
I can pass it to a view and return the title and entry
$this->widget('bootstrap.widgets.TbBox', array(
title' => $modelA['title'],
'content' => $modelA['entry'] ));
Now I'd like to return a range of entries
$criteria2 = new CDbCriteria();
$criteria2->condition = 'id > 7';
$modelB=Table1::model()->findAll($criteria2);
(btw : I'm following a form as laid out here). I was expecting to be able to read the resulting array of values out as below, but ['title'] is now being seen as a undefined index (obviously I'm expecting to read this out in a loop but you get the point)
$this->widget('bootstrap.widgets.TbBox', array(
'title' => $modelB['title'][0],
'content' => $modelB['entry'][0]));
Where am I going wrong?
Thanks
No, the indexes should be specified in the different order: the number of a specific element first, then the name of the property. Additionally, it's better (=cleaner) to name the result of findAll so it'll show you (and any other reader) that it's a collection, not a single model:
$models = Table1::model()->findAll($criteria2);
// ...
$this->widget('bootstrap.widgets.TbBox', array(
'title' => $models[0]['title']
//...
));
But even that's not necessary if you use foreach (and you probably will):
foreach ($models as $model):
// ...
$this->widget('some.name', array(
'title' => $model['title']
);
endforeach;
has just started out Yii web app and encountered this problem, any suggestions are welcome:)
What i am trying to achieve:
-To display a form with tabs, each tab content contains a list of checkboxes from the same model.
-so user can select some items from tab 1, some from tab 2, etc and then click submit button to process.
Problem:
But i couldn't think of anyway such that the last tab activecheckboxlist will not clobbered the previous one up.
I am trying to to something similar to this : [www.yiiframework.com/forum/index.php/topic/20388-2-checkboxlist-and-1-model]
but instead of fixing it at 2, mine is dynamic.
What i have done so far:
<?php
$tabArray = array();
foreach ((Product::model()->listParentChild(0)) as $productparent) {
array_push($tabArray, array(
'label' => $productparent['name'],
'content' => CHtml::activeCheckBoxList(
$model, 'products', CHtml::listData(Product::model()->listParentChild($productparent['id']), 'id', 'name'), array(
'labelOptions' => array('style' => 'display:inline'),
'template' => '<div class="check-option">{input} {label}</div>',
'separator' => '',
)
), 'active' => ($productparent['id'] == 1 ? true : false),
));
}
?>
<?php
$this->widget('bootstrap.widgets.TbTabs', array(
'type' => 'tabs', // 'tabs' or 'pills'
'placement' => 'left',
'tabs' => $tabArray,
));
?>
and in my product model:
public function listParentChild($parentid) {
$sql = "SELECT * FROM piki_product WHERE parentid=:parentid";
$productlist = Yii::app()->db->createCommand($sql);
$productlist->bindValue(":parentid", $parentid, PDO::PARAM_INT);
return $productlist->queryAll();
}
any suggestions will be appreciated.. :/
I could be wrong, but I don't think cliffbarnes is on the right track with his comments about dynamic nesting. As far as I can tell, you're only dealing with one level of child products; it's just that there could be multiple sets of these child products.
In that case, the link you sited actually offers the correct solution:
<?php echo CHtml::checkBoxList('array1', CHtml::listData(Atributos::model()-> findAllByAttributes(array('tipo'=>'talla')), 'id_atributo','valor'))?>
<?php echo CHtml::checkBoxList('array2', CHtml::listData(Atributos::model()-> findAllByAttributes(array('tipo'=>'talla')), 'id_atributo','valor'))?>
Each set of checkboxes is given a different name (array1, and array2), so that each field's selected values doesn't override the other. In your case, the solution is the same; you just need to make the field names dynamic. I.E.
foreach ((Product::model()->listParentChild(0)) as $productparent) {
$fieldname = 'product' . $productparent['id'];
echo CHtml::checkBoxList($fieldname, ... (etc)
Within your controller you would check to see whether there are results for each dynamic field name.
foreach ((Product::model()->listParentChild(0)) as $productparent) {
if (isset($_POST['product' . $productparent['id']]) {
// Add values to $model->product
}
}
An even better solution would be to output each checkbox individually, so you can create one array of results, indexed by child ID.
foreach ((Product::model()->listParentChild(0)) as $productparent) {
foreach (Product::model()->listParentChild($productparent['id']) as $child) {
CHtml::checkBox("product[{$child['id']}]", ... (etc)
Then in your controller, all you'd have to do is this:
if (isset($_POST['product']) && count($_POST['product']) > 0) {
$model->product = array_keys($_POST['product']);
}
This solution does not work with activeCheckBoxList(). It would work if you wanted to override the __get() and __set() magic methods to make these dynamic property names available to your model, but that's probably over kill.
Edit (as per request)
If you need to have default selections for your checkboxes, you can just pass them as the second argument of CHtml::checkBoxList(). http://www.yiiframework.com/doc/api/1.1/CHtml#checkBoxList-detail
But if you still want to use __get() and __set(), here's an example:
class YourModel extends CActiveRecord {
// I usually create a placeholder to contain the values of my virtual attribute
protected $_childValues = array();
public function __get($name) {
// The following regular expression finds attributes
// with the name product_{parent ID}
if (preg_match("/^product_\d+$/", $name)) {
// I put the underscore in the name so I could get
// parent ID easier.
list($junk, $id) = explode("_", $name);
if (!isset($this->_childValues[$id])) {
$this->_childValues[$id] = array();
}
return $this->_childValues[$id];
}
else {
// Make sure to still call the parent's __get() method
return parent::__get($name);
}
}
public function __set($name, $value) {
// Same regex as above
if (preg_match("/^product_\d+$/", $name)) {
list($junk, $id) = explode("_", $name);
$this->_childValues[$id] = $value;
}
else {
// Make sure to still call the parent's __set() method
parent::__set($name, $value);
}
}
}
$model = new YourModel;
// Any property in the format of product_{parent ID} is available
// through your model.
echo $model->product_1;
$model->product_300 = array();
You might also consider checking to see if the parent ID in a property name corresponds with a parent ID in the database, instead of just allowing any property in that format to pass through.
In my model I have a relation() like this.
'notRelUser' => array(
self::HAS_MANY,
'LocationUser',
'location_id',
'condition' => 'notRelUser.status is null',
'on' => 'notRelUser.user_id = ' . Yii::app()->user->getId(),
'with' => array('parent_location'),
'select' => array('*', 'name AS canApply'),
),
and this
public $canApply;
In my controller I have this
$regions = Location::model()->with('notRelUser')->findAll();
$arrayCanApply = new CArrayDataProvider($regions);
I then am trying to print out the value of canApply in a widget for datagrid
<?php $this->widget('bootstrap.widgets.TbGridView', array(
'dataProvider'=>$arrayCanApply,
'columns'=>array(
array('name'=>'name', 'header'=>'Name'),
array('name' => 'canApply', 'value'=>'$data->canApply', 'header'=>'CanApply'),
),
));
But the column with canApply is empty.
I have also tried without the $data-> part.
How can I print this alias?
(I know the value of the alias i trivial, but I will change that later)
UPDATE:
I can get the value by using select in CDbCriteria - but I want to do it in relation.
This does work.
$criteria = new CDbCriteria;
$criteria->select = '("foobar") AS canApply';
$regions = Location::model()->with('notRelUser')->findAll($criteria);
but it seems odd that I have to create a $criteria on everytime
you need to declare can canApply as an attribute of the model
in your model decalare canApply as an attribute
public $canApply;
I also had the same problem. Try 'value'=>'$data->notRelUser->canApply'
instead of 'value'=>'$data->canApply'. Also, you need to declare attribute
public $canApply;
in your LocationUser model, not in Location model.