Get Model or Record Attributes in Variable Types Specified by Defineattributes()

Problem

When Craft returns BaseModel and BaseRecord attributes, it doesn’t return them in the variables types specified by the defineAttributes method.

Solution

  • In your plugin’s Models, override the setAttribute method.
  • In your plugin’s Records, override the prepAttributesForUse method.
<?php

namespace Craft;

class Recurly_PlanModel extends BaseModel
{
    protected function defineAttributes() {
        return array(
            'sortOrder'     => AttributeType::SortOrder,
            'code'          => AttributeType::String,
            'max'           => AttributeType::Number,
            'min'           => AttributeType::Number,
            'baseEndpoints' => AttributeType::Number,
            'endpointCode'  => AttributeType::String,
            'annual'        => array('type' => AttributeType::Bool, 'default' => false),
            'baseCost'      => array('type' => AttributeType::Number, 'decimals' => 2),
            'endpointCost'  => array('type' => AttributeType::Number, 'decimals' => 2),
        );
    }

    public function setAttribute($name, $value)
    {
        parent::setAttribute($name, $value);
        if (in_array($name, $this->attributeNames()))
        {
            $attributes = $this->getAttributeConfigs();
            $config = $attributes[$name];

            // Handle special case attribute types
            switch ($config['type'])
            {
                case AttributeType::Bool:
                {
                    if ($value)
                    {
                        $value = (bool) $value;
                    }

                    break;
                }
                case AttributeType::Number:
                {
                    if ($value)
                    {
                        $value = floatval(number_format($value, $config['decimals']));
                    }

                    break;
                }
            }

            $this->$name = $value;
            return true;
        }
        else
        {
            return false;
        }
    }
}
<?php

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,
            'baseEndpoints' => AttributeType::Number,
            'endpointCode'  => AttributeType::String,
            'annual'        => array('type' => AttributeType::Bool, 'default' => false),
            'baseCost'      => array('type' => AttributeType::Number, 'decimals' => 2),
            'endpointCost'  => array('type' => AttributeType::Number, 'decimals' => 2),
        );
    }

    public function prepAttributesForUse()
    {
        parent::prepAttributesForUse();
        $attributes = $this->getAttributeConfigs();

        $attributes['dateUpdated'] = array('type' => AttributeType::DateTime, 'column' => ColumnType::DateTime, 'required' => true);
        $attributes['dateCreated'] = array('type' => AttributeType::DateTime, 'column' => ColumnType::DateTime, 'required' => true);

        foreach ($attributes as $name => $config)
        {
            $value = $this->getAttribute($name);

            switch ($config['type'])
            {
                case AttributeType::Bool:
                {
                    if ($value)
                    {
                        $this->setAttribute($name, (bool) $value);
                    }

                    break;
                }
                case AttributeType::Number:
                {
                    if ($value)
                    {
                        $value = floatval(number_format($value, $config['decimals']));
                        $this->setAttribute($name, $value);
                    }

                    break;
                }
            }
        }
    }
}

Discussion