Extending Model Meta - mymagic/open_hub GitHub Wiki

Meta

Meta allowing you to extends a model without changing database structure. As one of the method of flexible schema, this is helpful when module needs to add new attribute to one of the core model such as organization, individual, event...

Enable Meta for Model

Meta is not automatically enabled for all models, it has to be done thru coding by developer.

Refer here on how to name your meta variable.

public function init()
{
    // meta
    $this->initMetaStructure($this->tableName());
    parent::init();
}
public function rules()
{
    // NOTE: you should only define rules for those attributes that
    // will receive user inputs.
    $return = array(
        array('code, title', 'required'),
        ...
    );
    
    // meta
    $return[] = array('_dynamicData', 'safe');

    return $return;
}
public function relations()
{
    return array(
        ...
        // meta
        'metaStructures' => array(self::HAS_MANY, 'MetaStructure', '', 'on' => sprintf('metaStructures.ref_table=\'%s\'', $this->tableName())),
        'metaItems' => array(self::HAS_MANY, 'MetaItem', '', 'on' => 'metaItems.ref_id=t.id AND metaItems.meta_structure_id=metaStructures.id', 'through' => 'metaStructures'),
    );
}

OpenHub comes with built in function MetaStructure::initMeta to help you create the structure:

MetaStructure::initMeta('organization', 'sample', 'extraColumn1', 'boolean', 'Highlight in Sample', 'Is this organization a lighted sample?', '');

This will create a meta_structure record with code Organization-sample-extraColumn1 following naming convention where sample is the module code name and extraColumn1 is the variable name. Failed to do this will introduce errors to another matching Model name on save.

Get a meta structure

As simple as:

<?php echo $model->_dynamicData['Organization-sample-extraColumn1']

Query a meta structure

SQL join is required to query value from meta data.

SELECT o.id FROM organization as `o` 

INNER JOIN `meta_structure` as ms1 on ms1.ref_table='organization'
INNER JOIN `meta_item` as mi1 on mi1.meta_structure_id=ms1.id

INNER JOIN `meta_structure` as ms2 on ms2.ref_table='organization'
INNER JOIN `meta_item` as mi2 on mi2.meta_structure_id=ms2.id

WHERE  
(ms1.code='Organization-idea-membershipType'  AND mi1.ref_id=o.id) AND 
(ms2.code='Organization-idea-isEnterprise' AND mi2.value='1' AND mi2.ref_id=o.id) 

GROUP BY o.id ORDER BY o.title ASC

Known Issues

Meta Items value cant set due to bad code from modules' behavior

You tried to set value $org->_dynamicData[organization-abc'] = 'Hello World' but it is not working, meta value is not saved. But when you commented the following line from model Organization for example, the problem no longer exists.

public function behaviors()
{
    /*foreach (Yii::app()->modules as $moduleKey => $moduleParams) {
        if (isset($moduleParams['modelBehaviors']) && !empty($moduleParams['modelBehaviors']['Organization'])) {
            $return[$moduleKey] = Yii::app()->getModule($moduleKey)->modelBehaviors['Organization'];
            $return[$moduleKey]['model'] = $this;
        }
    }*/
}

This show the sign where one of your module (as long as it is initiated) is causing this issue.