How do I get model/record attributes in their proper types, and not just strings? 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'      =&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,
      ),
    );
  }
}


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()-&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 :(


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?
Currently the only thing Craft does in BaseModel->setAttribute() and BaseRecord->prepAttributesForUse() is some normalization when the attribute in either case happens to be AttributeType::DateTime or AttributeType::Mixed.

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-&gt;boolAttribute) will evaluate to true or false.

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