<p>Currently the only thing Craft does in <a href="http://buildwithcraft.com/classreference/models/BaseModel#setAttribute-detail" rel="nofollow">BaseModel->setAttribute()</a> and <a href="http://buildwithcraft.com/classreference/records/BaseRecord#prepAttributesForUse-detail" rel="nofollow">BaseRecord->prepAttributesForUse()</a> is some normalization when the attribute in either case happens to be <a href="http://buildwithcraft.com/classreference/enums/AttributeType" rel="nofollow">AttributeType::DateTime or AttributeType::Mixed</a>.</p>

<p>All other attribute types will be returned directly as the database returned them (as a string).</p>

<p>However, I agree with you that we probably should be doing more to return the exact type as the attribute specifies.  Since that's potentially a big breaking change, though, it'll have to wait until Craft 3.0.</p>

<p>The good news is, thanks to PHP's loose typing system, you can still workaround most cases.</p>

<p>For example a bool will come back as either the string <code>'1'</code> or <code>'0'</code>.</p>

<p>Using that in a PHP conditional <code>if ($myModel-&gt;boolAttribute)</code> will evaluate to true or false.</p>

<p>Using your float example: <code>'1402.50' + 100.00</code>, PHP will properly cast that to <code>1502.50</code>.</p>

CC BY-SA 3.0
2014-11-17T23:53:00.377Z
Thanks for the answer Brad. The way this came up is I had a controller just dumping models to json: `$this->returnJson($arrayOfModels);`, but noticed everything was strings when I really wanted to retain things that were floats, bool, etc.
Tim Kelty
CC BY-SA 3.0
2014-11-17T23:54:32.797Z
Ahh... in that case, you might just need to do some casting yourself.
Brad Bell
CC BY-SA 3.0
2014-11-17T23:56:17.920Z
I'm thinking I'll override the model constructor and do my casting there, if that makes sense. But +1 for getting this on the books for Craft 3!
Tim Kelty
CC BY-SA 3.0
2015-05-01T14:18:59.183Z
I'd like to point out that this is a Yii issue. The justification by the Yii development Team was that using strings to represent integers avoids integer overflow on 32-bit machines. Personally I still think it's a bit of a silly decision.
Jay
CC BY-SA 3.0
2014-11-17T23:40:28.827Z
2014-11-17T23:40:28.827Z
Brad Bell
<p>I ended up overriding BaseModel->setAttribute() and BaseRecord->prepAttributesForUse() in my plugin.</p>

<p>Works well! Right now I'm just handling Bool and Number types.</p>

<p>Posted this solution here: <a href="http://craftcookbook.net/recipes/324" rel="nofollow">http://craftcookbook.net/recipes/324</a></p>

CC BY-SA 3.0
2014-11-19T16:59:04.440Z
2014-11-19T22:10:43.267Z
2014-11-19T22:10:43.267Z
Tim Kelty
<p>Here's my record (model is nearly identical):</p>

<pre><code>namespace Craft;

class Recurly_PlanRecord extends BaseRecord
{

  public function getTableName()
  {
    return 'recurly_plans';
  }

  protected function defineAttributes()
  {
    return array(
      'sortOrder'      =&gt; AttributeType::SortOrder,
      'code'           =&gt; AttributeType::String,
      'max'            =&gt; AttributeType::Number,
      'min'            =&gt; AttributeType::Number,
      'annual'         =&gt; AttributeType::Bool,
      'base_endpoints' =&gt; AttributeType::Number,
      'endpoint_code'  =&gt; AttributeType::String,
      'base_cost'      =&gt; array(
        'type'     =&gt; AttributeType::Number,
        'decimals' =&gt; 2,
      ),
      'endpoint_cost'  =&gt; array(
        'type'     =&gt; AttributeType::Number,
        'decimals' =&gt; 2,
      ),
    );
  }
}
</code></pre>

<p>In the DB, the column types seem to be set correctly based on this.
What I can't figure out how to do, is actually get data back in the specified types, not just strings.</p>

<p>Here's me using it in a service:</p>

<pre><code>$record = Recurly_PlanRecord::model()-&gt;find();
var_dump($record-&gt;attributes); // all strings :(
var_dump($record-&gt;base_cost); // string '1402.50' (length=7)

$model  = Recurly_PlanModel::populateModel($record);
var_dump($model-&gt;attributes); // all strings :(
</code></pre>

<p>What I <em>want</em> is <code>float 1402.50</code>. What I get is a string.</p>

<p>I'm having the same problem with <code>AttributeType::Bool</code>.</p>

<p>What am I doing wrong?</p>

CC BY-SA 3.0
2014-11-15T04:51:23.153Z
Not sure if you are aware, but P&T recently added Craft::dd($variableName) as an option and has been very helpful when troubleshooting issues like this.
Jason McCallister
CC BY-SA 3.0
2014-11-17T17:17:43.910Z
Thanks @JasonMcCallister, didn't know about that. Getting the same results from `Craft::dd`, however. Showing strings for everything.
Tim Kelty
<plugin-development><string><models><records>
How do I get model/record attributes in their proper types, and not just strings?
# How do I get model/record attributes in their proper types, and not just strings?

(Asked by: username_0 on 2014-11-13)

Here's my record (model is nearly identical):
namespace Craft;

class Recurly_PlanRecord extends BaseRecord
{

  public function getTableName()
  {
    return 'recurly_plans';
  }

  protected function defineAttributes()
  {
    return array(
      'sortOrder'      => AttributeType::SortOrder,
      'code'           => AttributeType::String,
      'max'            => AttributeType::Number,
      'min'            => AttributeType::Number,
      'annual'         => AttributeType::Bool,
      'base_endpoints' => AttributeType::Number,
      'endpoint_code'  => AttributeType::String,
      'base_cost'      => array(
        'type'     => AttributeType::Number,
        'decimals' => 2,
      ),
      'endpoint_cost'  => array(
        'type'     => AttributeType::Number,
        'decimals' => 2,
      ),
    );
  }
}

In the DB, the column types seem to be set correctly based on this.
What I can't figure out how to do, is actually get data back in the specified types, not just strings.
Here's me using it in a service:
$record = Recurly_PlanRecord::model()->find();
var_dump($record->attributes); // all strings :(
var_dump($record->base_cost); // string '1402.50' (length=7)

$model  = Recurly_PlanModel::populateModel($record);
var_dump($model->attributes); // all strings :(

What I want is float 1402.50. What I get is a string.
I'm having the same problem with AttributeType::Bool.
What am I doing wrong?

**Tags:** plugin-development, string, models, records

> **Comments:**
> **username_1**: Not sure if you are aware, but P&T recently added Craft::dd($variableName) as an option and has been very helpful when troubleshooting issues like this.  
> **username_0**: Thanks @JasonMcCallister, didn't know about that. Getting the same results from `Craft::dd`, however. Showing strings for everything.  

---

## 2 answers

### Answer by username_2 on 2014-11-17. Score: 3 | Accepted answer

Currently the only thing Craft does in [BaseModel->setAttribute()](http://buildwithcraft.com/classreference/models/BaseModel#setAttribute-detail) and [BaseRecord->prepAttributesForUse()](http://buildwithcraft.com/classreference/records/BaseRecord#prepAttributesForUse-detail) is some normalization when the attribute in either case happens to be [AttributeType::DateTime or AttributeType::Mixed](http://buildwithcraft.com/classreference/enums/AttributeType).

All other attribute types will be returned directly as the database returned them (as a string).

However, I agree with you that we probably should be doing more to return the exact type as the attribute specifies. Since that's potentially a big breaking change, though, it'll have to wait until Craft 3.0.

The good news is, thanks to PHP's loose typing system, you can still workaround most cases.

For example a bool will come back as either the string `'1'` or `'0'`.

Using that in a PHP conditional `if ($myModel->boolAttribute)` will evaluate to true or false.

Using your float example: `'1402.50' + 100.00`, PHP will properly cast that to `1502.50`.

> **Comments:**
> **username_0**: Thanks for the answer Brad. The way this came up is I had a controller just dumping models to json: `$this->returnJson($arrayOfModels);`, but noticed everything was strings when I really wanted to retain things that were floats, bool, etc.  
> **username_2**: Ahh... in that case, you might just need to do some casting yourself.  
> **username_0**: I'm thinking I'll override the model constructor and do my casting there, if that makes sense. But +1 for getting this on the books for Craft 3!  
> **username_3**: I'd like to point out that this is a Yii issue. The justification by the Yii development Team was that using strings to represent integers avoids integer overflow on 32-bit machines. Personally I still think it's a bit of a silly decision.  

---

### Answer by username_0 on 2014-11-19. Score: 3

I ended up overriding BaseModel->setAttribute() and BaseRecord->prepAttributesForUse() in my plugin.

Works well! Right now I'm just handling Bool and Number types.

Posted this solution here: <http://craftcookbook.net/recipes/324>


---

