Yii Framework Forum: transform a model attribute value - Yii Framework Forum

Jump to content

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

transform a model attribute value Rate Topic: -----

#1 User is offline   GSTAR 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,035
  • Joined: 30-October 09
  • Location:UK

Posted 26 February 2010 - 06:23 AM

In my users table I have an "enabled" field - this can be set to either 1 or 0.

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?
0

#2 User is offline   jayrulez 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 348
  • Joined: 29-July 09

Posted 26 February 2010 - 06:31 AM

View PostGSTAR, on 26 February 2010 - 06:23 AM, said:

In my users table I have an "enabled" field - this can be set to either 1 or 0.

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.
0

#3 User is offline   GSTAR 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,035
  • Joined: 30-October 09
  • Location:UK

Posted 26 February 2010 - 06:44 AM

Hi jayRulez,

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?
0

#4 User is offline   GSTAR 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,035
  • Joined: 30-October 09
  • Location:UK

Posted 26 February 2010 - 06:49 AM

How can I reference $model->isEnabled in a CDetailView/CGridView?
0

#5 User is offline   jayrulez 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 348
  • Joined: 29-July 09

Posted 26 February 2010 - 07:02 AM

View PostGSTAR, on 26 February 2010 - 06:49 AM, said:

How can I reference $model->isEnabled in a CDetailView/CGridView?


...,
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.
1

#6 User is offline   Maurizio Domba Cerin 

  • Yii - Yesss It Is !!!
  • Yii
  • Group: Yii Dev Team
  • Posts: 4,349
  • Joined: 12-October 09
  • Location:Croatia

Posted 26 February 2010 - 07:57 AM

If I understand right you have a field "enabled" that is 1 or 0, but in the application you would like it to be "yes" or "no"...

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'.
Find more about me.... btw. Do you know your WAN IP?
1

#7 User is offline   GSTAR 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,035
  • Joined: 30-October 09
  • Location:UK

Posted 26 February 2010 - 08:05 AM

Thanks. Actually this also works too:

public function afterFind()
{
	$this->enabled = $this->enabled ? 'Yes' : 'No';
        return parent::afterFind();
}

1

#8 User is offline   Maurizio Domba Cerin 

  • Yii - Yesss It Is !!!
  • Yii
  • Group: Yii Dev Team
  • Posts: 4,349
  • Joined: 12-October 09
  • Location:Croatia

Posted 26 February 2010 - 08:14 AM

View PostGSTAR, on 26 February 2010 - 08:05 AM, said:

Thanks. Actually this also works too:



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.
Find more about me.... btw. Do you know your WAN IP?
0

#9 User is offline   jayrulez 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 348
  • Joined: 29-July 09

Posted 26 February 2010 - 09:01 AM

mdomba's approach is right on the ball for your situation but not the best thing to do. I take it in your code you'll want to use the 1/0 representation instead of 'Yes'/'No'. eg:
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.
0

#10 User is offline   intel352 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 196
  • Joined: 05-February 10
  • Location:Southport, NC

Posted 26 February 2010 - 09:35 AM

I agree that you should not transform the data *within* the model, as that will cause issues and dirty up your data model.

I personally only transform 0/1 into no/yes in the actual view, i.e.:
echo ($model->enabled ? 'yes' : 'no');

Need live Yii support? - Join the #yii IRC channel on Freenode!
1

#11 User is offline   GSTAR 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,035
  • Joined: 30-October 09
  • Location:UK

Posted 01 March 2010 - 10:55 AM

Quote

I personally only transform 0/1 into no/yes in the actual view
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!
0

#12 User is offline   intel352 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 196
  • Joined: 05-February 10
  • Location:Southport, NC

Posted 01 March 2010 - 11:11 AM

View PostGSTAR, on 01 March 2010 - 10:55 AM, said:

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!


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")',

Need live Yii support? - Join the #yii IRC channel on Freenode!
1

#13 User is offline   Y!! 

  • Advanced Member
  • Yii
  • Group: Yii Dev Team
  • Posts: 978
  • Joined: 18-June 09

Posted 01 March 2010 - 11:29 AM

View Postjayrulez, on 26 February 2010 - 06:31 AM, said:

Model:
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',

1

#14 User is offline   intel352 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 196
  • Joined: 05-February 10
  • Location:Southport, NC

Posted 01 March 2010 - 11:49 AM

Y!!'s method works for me ;)
Need live Yii support? - Join the #yii IRC channel on Freenode!
0

#15 User is offline   thyseus 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 300
  • Joined: 18-April 09
  • Location:Leipzig, Germany

Posted 01 March 2010 - 02:56 PM

You could also do a enum('Yes', 'No') as SQL Datatype.
0

#16 User is offline   intel352 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 196
  • Joined: 05-February 10
  • Location:Southport, NC

Posted 01 March 2010 - 04:48 PM

View Postthyseus, on 01 March 2010 - 02:56 PM, said:

You could also do a enum('Yes', 'No') as SQL Datatype.


Agreed that's a possibility, though enum is best reserved for a non-boolean response ;-)
But that would be a good alternative
Need live Yii support? - Join the #yii IRC channel on Freenode!
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