Hello,

I have implemented a meta cache for my modesl based on the tutorial-models-init example here

I have now:

<?php
use Phalcon\Mvc\ModelInterface,
    Phalcon\DiInterface,
    Phalcon\Mvc\Model\MetaData,
    Phalcon\Db\Column;

class MetaDataInitializer
{

    /**
     * Initializes the model's meta-data
     *
     * @param Phalcon\Mvc\ModelInterface $model
     * @param Phalcon\DiInterface $di
     * @return array
     */
    public function getMetaData(ModelInterface $model, DiInterface $di)
    {

        $reflection = $di['annotations']->get($model);
        $properties = $reflection->getPropertiesAnnotations();
        if (!$properties) 
        {
            throw new Exception("There are no properties defined on the class");
        }

        $attributes = array();
        $nullables = array();
        $dataTypes = array();
        $dataTypesBind = array();
        $numericTypes = array();
        $primaryKeys = array();
        $nonPrimaryKeys = array();
        $identity = false;

        foreach ($properties as $name => $collection) 
        {

            if ($collection->has('Column')) {

                $arguments = $collection->get('Column')->getArguments();

                /**
                 * Get the column's name
                 */
                if (isset($arguments['column'])) 
                {
                    $columnName = $arguments['column'];
                } 
                else {
                    $columnName = $name;
                }

                /**
                 * Check for the 'type' parameter in the 'Column' annotation
                 */
                if (isset($arguments['type'])) 
                {
                    switch ($arguments['type']) 
                    {
                        case 'integer':
                            $dataTypes[$columnName] = Column::TYPE_INTEGER;
                            $dataTypesBind[$columnName] = Column::BIND_PARAM_INT;
                            $numericTypes[$columnName] = true;
                            break;
                        case 'string':
                            $dataTypes[$columnName] = Column::TYPE_VARCHAR;
                            $dataTypesBind[$columnName] = Column::BIND_PARAM_STR;
                            break;
                        case 'text':
                            $dataTypes[$columnName] = Column::TYPE_TEXT;
                            $dataTypesBind[$columnName] = Column::BIND_PARAM_STR;
                            break;
                        case 'decimal':
                            $dataTypes[$columnName] = Column::TYPE_DECIMAL;
                            $dataTypesBind[$columnName] = Column::BIND_PARAM_DECIMAL;
                            break;                          
                        case 'enum':
                            $dataTypes[$columnName] = Column::TYPE_VARCHAR;
                            $dataTypesBind[$columnName] = Column::BIND_PARAM_STR;
                            break;                        
                        case 'boolean':
                            $dataTypes[$columnName] = Column::TYPE_BOOLEAN;
                            $dataTypesBind[$columnName] = Column::BIND_PARAM_BOOL;
                            break;
                        case 'date':
                            $dataTypes[$columnName] = Column::TYPE_DATE;
                            $dataTypesBind[$columnName] = Column::BIND_PARAM_STR;
                            break;
                        case 'datetime':
                            $dataTypes[$columnName] = Column::TYPE_DATETIME;
                            $dataTypesBind[$columnName] = Column::BIND_PARAM_STR;
                            break;
                    }
                } 
                else 
                {
                    $dataTypes[$columnName] = Column::TYPE_VARCHAR;
                    $dataTypesBind[$columnName] = Column::BIND_PARAM_STR;
                }

                /**
                 * Check for the 'nullable' parameter in the 'Column' annotation
                 */
                if (!$collection->has('Identity')) 
                {
                    if (isset($arguments['nullable'])) 
                    {
                        if (!$arguments['nullable']) 
                        {
                            $nullables[] = $columnName;
                        }
                    }
                }

                $attributes[] = $columnName;

                /**
                 * Check if the attribute is marked as primary
                 */
                if ($collection->has('Primary')) 
                {
                    $primaryKeys[] = $columnName;
                } 
                else 
                {
                    $nonPrimaryKeys[] = $columnName;
                }

                /**
                 * Check if the attribute is marked as identity
                 */
                if ($collection->has('Identity')) {
                    $identity = $columnName;
                }

            }

        }

        return array(

            //Every column in the mapped table
            MetaData::MODELS_ATTRIBUTES => $attributes,

            //Every column part of the primary key
            MetaData::MODELS_PRIMARY_KEY => $primaryKeys,

            //Every column that isn't part of the primary key
            MetaData::MODELS_NON_PRIMARY_KEY => $nonPrimaryKeys,

            //Every column that doesn't allows null values
            MetaData::MODELS_NOT_NULL => $nullables,

            //Every column and their data types
            MetaData::MODELS_DATA_TYPES => $dataTypes,

            //The columns that have numeric data types
            MetaData::MODELS_DATA_TYPES_NUMERIC => $numericTypes,

            //The identity column, use boolean false if the model doesn't have
            //an identity column
            MetaData::MODELS_IDENTITY_COLUMN => $identity,

            //How every column must be bound/casted
            MetaData::MODELS_DATA_TYPES_BIND => $dataTypesBind,

            //Fields that must be ignored from INSERT SQL statements
            MetaData::MODELS_AUTOMATIC_DEFAULT_INSERT => array(),

            //Fields that must be ignored from UPDATE SQL statements
            MetaData::MODELS_AUTOMATIC_DEFAULT_UPDATE => array()

        );
    }

    /**
     * Initializes the model's column map
     *
     * @param Phalcon\Mvc\ModelInterface $model
     * @param Phalcon\DiInterface $di
     * @return array
     */
    public function getColumnMaps(ModelInterface $model, DiInterface $di)
    {
        $reflection = $di['annotations']->get($model);

        $columnMap = array();
        $reverseColumnMap = array();

        $renamed = false;
        foreach ($reflection->getPropertiesAnnotations() as $name => $collection) 
        {

            if ($collection->has('Column')) {

                $arguments = $collection->get('Column')->getArguments();

                /**
                 * Get the column's name
                 */
                if (isset($arguments['column'])) 
                {
                    $columnName = $arguments['column'];
                } 
                else 
                {
                    $columnName = $name;
                }

                $columnMap[$columnName] = $name;
                $reverseColumnMap[$name] = $columnName;

                if (!$renamed) 
                {
                    if ($columnName != $name) 
                    {
                        $renamed = true;
                    }
                }
            }
        }

        if ($renamed) 
        {
            return array(
                MetaData::MODELS_COLUMN_MAP => $columnMap,
                MetaData::MODELS_REVERSE_COLUMN_MAP => $reverseColumnMap
            );
        }
        return null;
    }
}

and

<?php
use Phalcon\Events\Event,
    Phalcon\Mvc\Model\Manager as ModelsManager;

class AnnotationsInitializer extends Phalcon\Mvc\User\Plugin
{
    /**
     * This is called after initialize the model
     *
     * @param Phalcon\Events\Event $event
     */
    public function afterInitialize(Event $event, ModelsManager $manager, $model)
    {
        $reflector = $this->annotations->get($model);
        $annotations = $reflector->getClassAnnotations();
        if ($annotations) 
        {
            foreach ($annotations as $annotation) 
            {
                switch ($annotation->getName()) 
                {
                    case 'Source':
                        $arguments = $annotation->getArguments();
                        $manager->setModelSource($model, $arguments[0]);
                        break;

                    case 'hasOne':
                        $arguments = $annotation->getArguments();
                        if (isset($arguments[3])) 
                        {
                            $manager->addHasOne($model, $arguments[0], $arguments[1], $arguments[2], $arguments[3]);
                        } 
                        else 
                        {
                            $manager->addHasOne($model, $arguments[0], $arguments[1], $arguments[2]);
                        }
                        break;

                    case 'hasMany':
                        $arguments = $annotation->getArguments();
                        if (isset($arguments[3])) 
                        {
                            $manager->addHasMany($model, $arguments[0], $arguments[1], $arguments[2], $arguments[3]);
                        } 
                        else 
                        {
                            $manager->addHasMany($model, $arguments[0], $arguments[1], $arguments[2]);
                        }
                        break;

                    case 'hasManyToMany':
                        $arguments = $annotation->getArguments();
                        if (isset($arguments[6])) 
                        {
                            $manager->addHasManyToMany($model, $arguments[0], $arguments[1], $arguments[2], $arguments[3], $arguments[4], $arguments[5], $arguments[6]);
                        } 
                        else 
                        {
                            $manager->addHasManyToMany($model, $arguments[0], $arguments[1], $arguments[2], $arguments[3], $arguments[4], $arguments[5]);
                        }
                        break;

                    case 'belongsTo':
                        $arguments = $annotation->getArguments();
                        if (isset($arguments[3])) 
                        {
                            $manager->addBelongsTo($model, $arguments[0], $arguments[1], $arguments[2], $arguments[3]);
                        } 
                        else 
                        {
                            $manager->addBelongsTo($model, $arguments[0], $arguments[1], $arguments[2]);
                        }
                        break;

                }
            }
        }
    }
}

I have a model like this:

<?php
/**
 * Articles
 *
 * Model Articles
 *
 * @Source('articles');
 * @useDynamicUpdate(true);
 * @belongsTo('publishid','Users','id', {'alias': 'publisher'});
 * @hasOne('iconid','Images','id', {'alias': 'icon'});
 */
class Articles extends \Phalcon\Mvc\Model
{
    /**
     * @Primary
     * @Identity
     * @Column(type="integer", nullable=false, column="id", size="11")
     */
    public $id;

    /**
     * @Column(type="string", nullable=false, column="languagekey", size="3")
     */
    public $languagekey;

    /**
     * @Column(type="integer", nullable=false, column="iconid", size="11")
     */
    public $iconid;

    /**
     * @Column(type="integer", nullable=false, column="publishid")
     */
    public $publishid;  

    /**
     * @Column(type="string", nullable=false, column="pagetitle", size="100")
     */
    public $pagetitle;

    /**
     * @Column(type="string", nullable=false, column="listtitle", size="100")
     */
    public $listtitle;

    /**
     * @Column(type="string", nullable=false, column="listdescription", size="250")
     */
    public $listdescription;

    /**
     * @Column(type="text", nullable=false, column="content")
     */
    public $content;
}

The cache works perfect. There are files written, but the hasOne relations does not work. when I use for example


$article=Article::findFirst(12);
echo $article->listtitle."<br />";
echo $article->icon->thumbnail."<br />";

It says:
Notice: Trying to get property of non-object in /hosts/application/frontend/app/controllers/ArticlesController.php on line 24
(where $article->icon->thumbnail is on line 24)

The belonsgTo relation works fine.

My question:
Do I forgot something, or is there a fix for this?