Is The "order" Property in CDbCriteria Secure? - yii

Is the following code secure against the SQL injection?
$criteria = new CDbCriteria();
$arySort= json_decode($_GET['sort']);
$criteria->order= $arySort[0]->property . ' ' . $arySort[0]->direction;
Person::model()->findAll($criteria);
If not, what should I do to make sure there is no danger in the "order" property of the CDbCriteria object?
Should I use mysql_real_escape_string?

I think it's not enogh think only about sql injection. You have to check data from json array, couse wrong field name or wrong direction could be sent.
So
$criteria = new CDbCriteria();
$arySort= json_decode($_GET['sort']);
$criteria->order=$this->prepareSort($_GET['sort']);
Person::model()->findAll($criteria);
public function prepareSort($arySort)
{
$property='t.id';
$direction='ASC'
if(is_seet($arySort[0])
{
if(in_array($arySort[0]->property, array_keys($this->attributes))
$property=$arySort[0]->property;
if(in_array($arySort[0]->direction, array('ASC', 'DESC')))
$direction=$arySort[0]->direction;
}
return $property.' '.$direction;
}
PS
In the case of using CGridView something like this
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('t.id',$this->id);
$criteria->compare('t.title',$this->title,true);
$criteria->compare('content',$this->content,true);
$criteria->compare('url',$this->url,true);
return new CActiveDataProvider(
$this,
array(
'criteria'=>$criteria,
'sort'=>array(
'defaultOrder'=>'title ASC',
'attributes'=>array(
'*'
)
),
'pagination'=>array(
'pageSize'=>20,
),
)
);
}

Related

how to convert query with multiple group by columns to CActiveDataProvider in Yii 1.1.14?

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)
));
}
?>

How to get names in alphabetic order in Yii

In my Yii web application, having student table for saving student details. I want to student name in alphabetical order when retrieve data from student table.
public function defaultScope() {
return array("order" => "student_firstname");
}
I tried this function, but not working properly.
Please help me.
Thanks in advance.
you can use the defaultOrder property of CSort. For example...
$dataProvider=new CActiveDataProvider('Example', array(
'sort'=>array(
'defaultOrder'=>array(
'student_firstname'=>false
)
)
));
In model's search method for data provider try to set default order, like this:
$dataProvider=new CActiveDataProvider($this, array(
'sort'=>array(
'defaultOrder'=> 'student_firstname ASC'
)
));
In model's search method for data provider try to set default order, like this:
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'pagination'=>array(
'pageSize'=>Yii::app()->params['defaultPageSize'],
),
'sort'=>array(
'defaultOrder'=>array(
'student_firstname'=>CSort::SORT_ASC
),
),
));

CListView filtering by value

is there a parameter that I can use with ClistView to get the commments of a given post_id
<?php $this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_comment',
'template'=>"{items}\n{pager}",
)); ?>
I'd like to add post_id = value in order to only list the comment with the given post_id
I put a search function in my comment model
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('post_id',$this->post_id,true);
return new CActiveDataProvider('Comment', array(
'criteria'=>$criteria,
'sort'=>array(
'defaultOrder'=>'status, create_time DESC',
),
));
}
Thank in advance for your help. I cannot find in the documentation.

multi comparison in cgridview in yii

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)

Use column alias in dataProvider

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.