Yii 1.1: Instantiate a child class that depends a type field from parent model class (CActiveRecord)

4 followers

[EN] [ES]

Sometimes we have an scenario like this:

class AnimalType extends CActiveRecord {} // Table with the "types" of Animals available
 
class Animal extends CActiveRecord { // Parent model class
  // Model based on a table with a field: type_id
  // that stores the type of the Animal
}
 
class Cat extends Animal {} // Child class
 
class Dog extends Animal {}

And we'd like to do something like:

// This statement will return a "Cat" instance
$someAnimal = Animal::model()->findByPk(1);

Since Yii implements a factory design model, it's very easy to implement a simple and quick solution for this.

Step 1 (and unique) Override instantiate() function. I included the PhpDoc comments present in CActiveRecord

/**
     * Creates an active record instance.
     * This method is called by {@link populateRecord} and {@link populateRecords}.
     * You may override this method if the instance being created
     * depends the attributes that are to be populated to the record.
     * For example, by creating a record based on the value of a column,
     * you may implement the so-called single-table inheritance mapping.
     * @param array $attributes list of attribute values for the active records.
     * @return MyClass the active record
     */
    protected function instantiate($attributes)
    {
        if (!isset($attributes['type_id'])) { // When creating and $type_id has not defined yet
            return parent::instantiate($attributes);
        }
        $classRecord = AnimalType::model()->findByPk($attributes['type_id']); // Load the "Type" class
        if($classRecord === null)
            throw new CException('Type not found');
        $className = $classRecord->name; // Let's assume that name is the field storing the name of the class
        $model = new $className(null); // Null param needed for populating the record
        return $model;
    }

Very easy, right. Enjoy and share :) If you find some grammar, spelling or language mistake, feel free to fix it or report it to me. English is not my native language

Total 2 comments

#10467 report it
robregonm at 2012/10/30 09:44am
Question

What is "$class" in "if($class === null)" ?

@horechek

Sorry, It's a small, typo. The correct statement is:

if($classRecord === null)

Fixing. Thanks for reporting.

#10462 report it
horechek at 2012/10/30 04:09am
Question

What is "$class" in "if($class === null)" ?

Leave a comment

Please to leave your comment.

Write new article