Yii Framework Forum: avoid eval() on CGridView columns' values - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

avoid eval() on CGridView columns' values Make Yii work on a server where eval() is disabled Rate Topic: -----

#1 User is offline   Fran├žois Gannaz 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 87
  • Joined: 24-November 09

Posted 24 March 2010 - 08:40 AM

I'll have to deploy a Yii application on a server where eval() is disabled (for security reasons). And I can't make my application avoid using eval() without major changes. For instance it seems that CGridView depends on eval().

Here a short extract of my code:
$this->widget(
    'zii.widgets.grid.CGridView',
    array(
        'columns' => array(
            array(
                'name' => 'word',
                'type' => 'raw',
                'value' => 'CHtml::link($data->keyword, array("keyword/view", "id" => $data->id),'
                    .' array("title" => $data->notes, "class" => "keyword"))',
            ),


Apart from the ugliness of putting code in a string (hard not to forget a parenthesis), my problem is this code relies on eval(). Looking in the doc, I saw I coud probably define columns by extending CDataColumn, but this class still expects a "value" attribute that gets evaled. Is there a way to use a function that would receive $data as parameter? Something like:
class MyColumn extends CDataColumn
{
    function getValue($data) // would be used instead of $this->value
    {
        return CHtml::link(
            $data->keyword,
            array("keyword/view", "id" => $data->id),
            array("title" => $data->notes, "class" => "keyword")
        );
    }


I know someone posted on "eval() is evil" last month, especially thinking of HipHop, but contrary to this, I don't want to delete the eval() uses from the Yii code, I'm just looking for a way to avoid it in my application.
-1

#2 User is offline   Fran├žois Gannaz 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 87
  • Joined: 24-November 09

Posted 26 March 2010 - 11:25 AM

If anyone has the same problem, it's just that the documentation isn't very clear. It says that the attributes "value" will be evaled. But Yii doesn't use eval() but CComponent::evaluateExpression(). If given an array, it will behave like call_user_func_array().

So I replaced:
                'value' => 'CHtml::link($data->keyword, array("keyword/view", "id" => $data->id),'
                    .' array("title" => $data->notes, "class" => "keyword"))',

with:
                'value' => array($model, 'htmlColumn'), // calls $model->htmlColumn($data)


I couldn't find a way to pass a parameter, but at least I avoided eval().
0

#3 User is offline   Chris83 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 440
  • Joined: 27-February 10
  • Location:Helsinki, Finland

Posted 28 March 2010 - 06:08 PM

One way to avoid eval() would be to use anonymous functions (PHP 5.3).
http://php.net/manua...s.anonymous.php
Best regards,
Chris

My contribution to the Yii community:
Account | Yiistrap | Auth | Bootstrap | NordCms | Rights | LESS | SEO | Img

Follow me:
Twitter | GitHub | Bitbucket
0

#4 User is offline   vamp 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 181
  • Joined: 30-January 09

Posted 29 March 2010 - 03:09 AM

View PostChris83, on 28 March 2010 - 06:08 PM, said:

One way to avoid eval() would be to use anonymous functions (PHP 5.3).
http://php.net/manua...s.anonymous.php


First of all - try to check CComponent.evaluateExpression:

	public function evaluateExpression($_expression_,$_data_=array())
	{
		if(is_string($_expression_))
		{
			extract($_data_);
			return eval('return '.$_expression_.';');
		}
		else
		{
			$_data_[]=$this;
			return call_user_func_array($_expression_, $_data_);
		}
	}


If you provide an array - argument called as function!
-Posted Image-
Thanks, you make me stronger!
-1

#5 User is offline   Chris83 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 440
  • Joined: 27-February 10
  • Location:Helsinki, Finland

Posted 29 March 2010 - 09:35 AM

View Postvamp, on 29 March 2010 - 03:09 AM, said:

First of all - try to check CComponent.evaluateExpression:

	public function evaluateExpression($_expression_,$_data_=array())
	{
		if(is_string($_expression_))
		{
			extract($_data_);
			return eval('return '.$_expression_.';');
		}
		else
		{
			$_data_[]=$this;
			return call_user_func_array($_expression_, $_data_);
		}
	}


If you provide an array - argument called as function!


I didn't either find a way to pass parameters to call_user_func_array() called by CComponent->evaluateExpression(). Is there a way for doing this?
Best regards,
Chris

My contribution to the Yii community:
Account | Yiistrap | Auth | Bootstrap | NordCms | Rights | LESS | SEO | Img

Follow me:
Twitter | GitHub | Bitbucket
0

#6 User is offline   bettor 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 756
  • Joined: 02-February 09

Posted 29 March 2010 - 10:38 AM

View PostChris83, on 29 March 2010 - 09:35 AM, said:

I didn't either find a way to pass parameters to call_user_func_array() called by CComponent->evaluateExpression(). Is there a way for doing this?


I've been looking for the same solution. I am now thinking to override the evaluateExpression() method unless the staff provide an advice.

regards,
bettor
0

#7 User is offline   vamp 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 181
  • Joined: 30-January 09

Posted 29 March 2010 - 04:22 PM

View Postbettor, on 29 March 2010 - 10:38 AM, said:

I've been looking for the same solution. I am now thinking to override the evaluateExpression() method unless the staff provide an advice.

regards,
bettor


oh, guys!
try to provide:

'value'=>array($this,'myDataRender'),


and add your model in current context and parametrize it

public function myDataRender($data,$row,$grid){
 $this->myCurrentModel->setSomeDataProperty($data->property);
 return $this->myCurrentModel->renderSomeText($data->someProperty);
}

-Posted Image-
Thanks, you make me stronger!
0

#8 User is offline   Chris83 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 440
  • Joined: 27-February 10
  • Location:Helsinki, Finland

Posted 29 March 2010 - 04:41 PM

View Postvamp, on 29 March 2010 - 04:22 PM, said:

oh, guys!
try to provide:

'value'=>array($this,'myDataRender'),


and add your model in current context and parametrize it

public function myDataRender($data,$row,$grid){
 $this->myCurrentModel->setSomeDataProperty($data->property);
 return $this->myCurrentModel->renderSomeText($data->someProperty);
}



I don't see how this could work with e.g. an accessRules() 'expression'.

It would be nice if I could use an expression like this:

'expression'=>array(array(Yii::app()->user, 'checkAccess'), array('viewUser')),

Best regards,
Chris

My contribution to the Yii community:
Account | Yiistrap | Auth | Bootstrap | NordCms | Rights | LESS | SEO | Img

Follow me:
Twitter | GitHub | Bitbucket
0

#9 User is offline   vamp 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 181
  • Joined: 30-January 09

Posted 29 March 2010 - 06:12 PM

View PostChris83, on 29 March 2010 - 04:41 PM, said:

I don't see how this could work with e.g. an accessRules() 'expression'.

It would be nice if I could use an expression like this:

'expression'=>array(array(Yii::app()->user, 'checkAccess'), array('viewUser')),



'value'=>array($this,'checkAccess'),

...


public function checkAccess($data){
  return call_user_func_array(array(Yii::app()->user,'checkAccess'),array('viewUser',$data));
}


or no?
-Posted Image-
Thanks, you make me stronger!
0

#10 User is offline   Chris83 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 440
  • Joined: 27-February 10
  • Location:Helsinki, Finland

Posted 30 March 2010 - 01:13 AM

View Postvamp, on 29 March 2010 - 06:12 PM, said:

'value'=>array($this,'checkAccess'),

...


public function checkAccess($data){
  return call_user_func_array(array(Yii::app()->user,'checkAccess'),array('viewUser',$data));
}


or no?


I'm not sure I understand what you mean, could you explain a bit?
Best regards,
Chris

My contribution to the Yii community:
Account | Yiistrap | Auth | Bootstrap | NordCms | Rights | LESS | SEO | Img

Follow me:
Twitter | GitHub | Bitbucket
0

#11 User is offline   bettor 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 756
  • Joined: 02-February 09

Posted 30 March 2010 - 07:48 AM

View Postvamp, on 29 March 2010 - 04:22 PM, said:

oh, guys!
try to provide:

'value'=>array($this,'myDataRender'),


and add your model in current context and parametrize it

public function myDataRender($data,$row,$grid){
 $this->myCurrentModel->setSomeDataProperty($data->property);
 return $this->myCurrentModel->renderSomeText($data->someProperty);
}



Thanks for your help. Yii cannot find the third argument for myDataRender: Missing argument 3 for MyController::myDataRender();

Can you please suggest how I can obtain the value of one of the CGrudView columns in myDataRender() according to which I would like to calculate which css class to display?

Thank you in advance.

Regards,
bettor
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users