Formatting CDetailView attribute using function

Hi there,

On my index page I have a CGridView in which one of the columns I format using my own function (to generate image in it along with corresponding hint):


<?php

    	$this->widget('zii.widgets.grid.CGridView', array

    	(

       		...

            	'columns'=>array

            	(

                    	...

                    	array

                    	(

                            	'name'=>'STAT',

                            	'type'=>'raw',

                            	'value'=>'generateImgTag($data->STAT)',

                    	),

            	),

    	));


    	function generateImgTag($status)

    	{

            	$hint = 'Status zlecenia: '

            	$img = '<img title="'.$hint.'" src="'.Yii::app()->request->baseUrl.'/gfx/status_'.strtolower($status).'.gif" width="25" height="15" alt="'.$hint.'" border="0">';


            	return $img;

    	}

?>

Clicking on button in CButtonColumn of this CGridView leads user to a detail page, where I use CDetailView instead. It uses the same model, therefore, its attributes are the same as CGridView columns. But when I’m trying to format the same (STAT) column using the same function:


<?php

    	$this->widget('zii.widgets.CDetailView', array

    	(

            	'data'=>$model,

            	'attributes'=>array

            	(

                    	'BCODE',

                    	'DATR',

                    	'DATZ',

                    	array

                    	(

                            	'name'=>'STAT',

                            	'type'=>'raw',

                            	'value'=>'generateImgTag($data->STAT)',

                    	),

            	),

    	));

?>

I’m getting function name just written (treated as a string?). Can I use the same function to format CDetailView row or the only option is to use CDetailView’s itemTemplate and code image tag inside it?

CDetailView does not use "deferred" evaluation like CGridView does on rendering rows. If you remove the quotes it should work.

/Tommy

Thanks again (+1), Tommy.

Of course I had to change it to:


<?php

    	$this->widget('zii.widgets.CDetailView', array

    	(

            	'data'=>$model,

            	'attributes'=>array

            	(

                    	...

                    	array

                    	(

                            	'name'=>'STAT',

                            	'type'=>'raw',

                            	'value'=>generateImgTag($model->STAT),

                    	),

            	),

    	));

?>

Because $data is undefined here. But works, and that is most important.

It would be really nice if there was a way to get CDetailView to support deferred evaluation (in addition to just being more consistent if it did). I’ve had a few places where I could really have used that ability.

Looks like it could be done with a single line change in yii/framework/zii/widgets/CDetailView.php,

replace near line 208:

“$value=$attribute[‘value’];”

with

“$value=$this->evaluateExpression($attribute[‘value’],array(‘data’=>$this->data));”

Though i would like to point out that it seems like it would be a lot safer in BOTH the existing CGridView widget and proposed changed CDetailView widget, to force the use of a different attribute name if you want the text EVAL’d.

So that

‘value’=>‘whatever’

would not cause the widget to try to eval ‘whatever’

while

‘evalue’=>‘whatever’

WOULD cause the widget to try to eval ‘whatever’

the way it is now seems like an EXTREMELY ripe target for someone to exploit simply by providing a text string that is a valid php expression.

this seems like a serious security risk the way it is now.

Thanks, I’d been looking everywhere for a way to modify values in the CDetailView ‘attributes’ so I can display data from a referenced table rather than the foreign key to that table.

In my case…




	'attributes'=>array(

		'section_id',

		'name',

		'description',

		// ***  need to have the actual section type name here instead of the section_type_id as was the default ***

          	array

            	(

                   	 'name'=>'Group Type',

                   	 'type'=>'raw',

                   	 'value'=>SectionType::model()->findByPk($model->section_type_id)->name

            	),

		'join_code',

		// *** same with the parent section name instead of the Id ***

        	array

            	(

                    	'name'=>'Parent Section',

                    	'type'=>'raw',

                    	'value'=>Section::model()->findByPk($model->parent_section_id)->name

            	),



Thanks!

There is an easy way to display data from a referenced table instead of the id.

You just need to set the relations in the model.

Regards,

Diego Toala

MODEL


public function relations()

	{

		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		return array(

			

			'referencedTable' => array(self::BELONGS_TO, 'referencedTable', 'referenced_id'),

			

		);

	}

VIEW




            array(

                    'label'=>'Referenced Table',

                    'value'=>$model->referencedTable->name

                ),