transform a model attribute value
#1
Posted 26 February 2010 - 06:23 AM
I want to be able to set up in my model a way of transforming this value to a more friendly value i.e. 1="Yes", 0="No".
I can of course do this manually in each view via IF statements but ideally I want this process to be automated in the model so that it's available anywhere that I call $model->enabled - is this possible?
#2
Posted 26 February 2010 - 06:31 AM
GSTAR, on 26 February 2010 - 06:23 AM, said:
I want to be able to set up in my model a way of transforming this value to a more friendly value i.e. 1="Yes", 0="No".
I can of course do this manually in each view via IF statements but ideally I want this process to be automated in the model so that it's available anywhere that I call $model->enabled - is this possible?
Model:
public function getIsEnabled()
{
return $this->enabled ? 'Yes' : 'No';
}
View:
... echo $model->isEnabled; ...
php:
foreach(array('cat', 'dog', 'cow') as $animal) echo $animal."\n";
python:
[(animal, print(animal)) for animal in ['cat', 'dog', 'cow']]
ruby:
['cat', 'dog', 'cow'].each {|animal| puts animal}
You say Tomato, I say Tomato.
#3
Posted 26 February 2010 - 06:44 AM
Thanks, that's exactly what my colleague has suggested, but I was hoping there was a way of doing this automatically, i.e. without having to call any function?
#4
Posted 26 February 2010 - 06:49 AM
#5
Posted 26 February 2010 - 07:02 AM
GSTAR, on 26 February 2010 - 06:49 AM, said:
..., array( 'name' => 'enabled', 'value' => $model->isEnabled, ), ...
/
..., array( 'name' => 'enabled', 'value' => '$data->isEnabled', ), ...
php:
foreach(array('cat', 'dog', 'cow') as $animal) echo $animal."\n";
python:
[(animal, print(animal)) for animal in ['cat', 'dog', 'cow']]
ruby:
['cat', 'dog', 'cow'].each {|animal| puts animal}
You say Tomato, I say Tomato.
#6
Posted 26 February 2010 - 07:57 AM
You could use a custom behavior to change the value of enabled, but I'm not sure if that is goot programing practice...
Something like this would work:
myEnable.php - put it for example in protected/components
class myEnable extends CActiveRecordBehavior
{
/**
* Convert from Yes/No to 1/0
*/
public function beforeSave($event)
{
$this->Owner->enabled = $this->Owner->enabled == 'Yes' ? '1' : '0';
return parent::beforeSave($event);
}
/**
* Convert from 1/0 to Yes/No
*/
public function afterFind($event)
{
$this->Owner->enabled = $this->Owner->enabled ? 'Yes' : 'No';
return parent::afterFind($event);
}
}
now in the model you attach this behavior like:
public function behaviors(){
return array(
'myEnable'=>array(
'class'=>'application.components.myEnable',
),
);
}
Note that with this in place the enabled property now is Yes or No, not anymore 1 or 0... so if you make create/updates rules, you have to check not for integer 1/0 but for text 'Yes'/'No'.
#7
Posted 26 February 2010 - 08:05 AM
public function afterFind()
{
$this->enabled = $this->enabled ? 'Yes' : 'No';
return parent::afterFind();
}
#8
Posted 26 February 2010 - 08:14 AM
GSTAR, on 26 February 2010 - 08:05 AM, said:
Sure it works... the behavior variant is just to make it a re-usable component...
NOTE: If you are going to save some data for this model than you should add the beforeSave() method that returns the value to what the database expects.
#9
Posted 26 February 2010 - 09:01 AM
if($model->enabled == 1)instead of
if($model->enabled == 'Yes')... Otherwise i don't see any good reason to store 1/0 in the field when you always use it as 'Yes'/'No'.
What I usually do is define class constants to represent states e.g. for your case i'd do
const ENABLED_NO = 0; const ENABLED_YES = 1;
so a comparison
if($model->enabled == User::ENABLED_NO)is more meaningful to a reader than
if($model->enabled == 0)
It's fine to use 1/0 if you'll be the only one reading the source code and/or if it's properly documented.
php:
foreach(array('cat', 'dog', 'cow') as $animal) echo $animal."\n";
python:
[(animal, print(animal)) for animal in ['cat', 'dog', 'cow']]
ruby:
['cat', 'dog', 'cow'].each {|animal| puts animal}
You say Tomato, I say Tomato.
#10
Posted 26 February 2010 - 09:35 AM
I personally only transform 0/1 into no/yes in the actual view, i.e.:
echo ($model->enabled ? 'yes' : 'no');
#11
Posted 01 March 2010 - 10:55 AM
Quote
echo ($model->enabled ? 'yes' : 'no');
Funnily enough this actually seems like the best solution! So simple and I don't have to create any new fucntions or variables!
In fact I would prefer to use this method but not sure how I could do it in a CGridView or CDetailView!
#12
Posted 01 March 2010 - 11:11 AM
GSTAR, on 01 March 2010 - 10:55 AM, said:
In fact I would prefer to use this method but not sure how I could do it in a CGridView or CDetailView!
Per the API documentation, you can pass expressions into CGridView (and I assume CDetailView).
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns'=>array(
'title', // display the 'title' attribute
'category.name', // display the 'name' attribute of the 'category' relation
'content:html', // display the 'content' attribute as purified HTML
array( // display 'create_time' using an expression
'name'=>'create_time',
'value'=>'date("M j, Y", $data->create_time)',
),
array( [b]// display 'author.username' using an expression[/b]
'name'=>'authorName',
'value'=>'$data->author->username',
),
array( // display a column with "view", "update" and "delete" buttons
'class'=>'CButtonColumn',
),
),
));
So you could just try something like:
'value'=>'($data->enabled ? "yes" : "no")',
#13
Posted 01 March 2010 - 11:29 AM
jayrulez, on 26 February 2010 - 06:31 AM, said:
public function getIsEnabled()
{
return $this->enabled ? 'Yes' : 'No';
}
View:
... echo $model->isEnabled; ...
I think this is best solution since you write less code.
Think about this:
'value' => '$data->isEnabled',
instead of
'value' => '$data->enabled ? Yii::t("words", "yes") : Yii::t("words", "no")'Maybe it's also better to use "Value" as method suffix so you can also do things like this:
public function getCreatedAtValue()
{
return date("M j, Y", $this->createdAt);
}
'value'=>'$data->createdAtValue',
#14
Posted 01 March 2010 - 11:49 AM
#16
Posted 01 March 2010 - 04:48 PM
thyseus, on 01 March 2010 - 02:56 PM, said:
Agreed that's a possibility, though enum is best reserved for a non-boolean response ;-)
But that would be a good alternative

Help













