Implementation of yii framework model class and Application of PhP5 Dynamic Language Features

Source: Internet
Author: User

The yii framework provides a code generator Gii, which is generally used to generate model-class code. The model class encapsulates data (table) operations.

However, in the model class, you cannot see the get/set attribute method, or even the attribute member variables associated with the table fields, but they do not affect direct operations on the attributes, it seems that these attributes are there.

The specific implementation method is a good application case of some design patterns and PhP5 dynamic language features.

For example, for the next user model class, the corresponding data table is users.

<?phpclass User extends CActiveRecord{/** * The followings are the available columns in table 'users': * @var double $Id * @var string $Username * @var string $Password * @var string $Email *//** * Returns the static model of the specified AR class. * @return CActiveRecord the static model class */public static function model($className='User'){return parent::model($className);}/** * @return string the associated database table name */public function tableName(){return 'users';}}

To read a user record, we must first construct a user object.

$ User = new user ();

Run var_dump ($ user). You will find that $ user has a private _ MD attribute (metadata of the model). The attribute type is cactiverecordmetadata.

The _ MD variable contains the schema of the data table ).

What code will be executed to construct such an object and read the data table structure definition? Let's track it below:

1. Like other object-oriented languages, when calling New to create an object, the class constructor is called first, as shown below:

/** * Constructor. * @param string $scenario scenario name. See {@link CModel::scenario} for more details about this parameter. */public function __construct($scenario='insert'){if($scenario===null) // internally used by populateRecord() and model()return;$this->setScenario($scenario);$this->setIsNewRecord(true);$this->_attributes=$this->getMetaData()->attributeDefaults;$this->init();                ......}

We can see that the model constructor calls the getmetadata method and also gives the default value to the attribute member variable ($ this-> _ attributes) of the model object.

It seems that the construction of the model object metadata and the reading of the data table Shema are related to this function.

/** * Returns the meta-data for this AR * @return CActiveRecordMetaData the meta for this AR class. */public function getMetaData(){if($this->_md!==null)return $this->_md;elsereturn $this->_md=self::model(get_class($this))->_md;}

The getmetadata function calls the self: model method. This function is familiar with. It is a static method and returns a static instance of the model class based on the class name.

/** * Returns the static model of the specified AR class. * The model returned is a static instance of the AR class. */public static function model($className=__CLASS__){if(isset(self::$_models[$className]))return self::$_models[$className];else{$model=self::$_models[$className]=new $className(null);$model->_md=new CActiveRecordMetaData($model);$model->attachBehaviors($model->behaviors());return $model;}}

Note: Self: $ _ models is a static variable in singleton mode. All models loaded by your application are managed in this object array, you can think of it as a centralized model object manager. It seems that even if the model is no longer used, the created model object will not be released. The code above creates a cactiverecordmetadata object, that is, the schema of the aforementioned data table. Note that the user model itself is passed as a parameter of its constructor, this is similar to the application of a delegate mode, that is, the model class delegates the task of obtaining the data table schema to the cactiverecordmetadata class. Continue reading,

    /**     * Constructor.     * @param CActiveRecord $model the model instance     */    public function __construct($model)    {        $this->_model=$model;        $tableName=$model->tableName();        if(($table=$model->getDbConnection()->getSchema()->getTable($tableName))===null)            throw new CDbException(Yii::t('yii','The table "{table}" for active record class "{class}" cannot be found in the database.',                array('{class}'=>get_class($model),'{table}'=>$tableName)));        ......    }

In the above Code, gettable ($ tablename) is called by the gettable ('user') function to call the loadtable method of cmysqlschema.

SHOW FULL COLUMNS FROM ...

The structure definition of the data table is obtained and assigned to the model object.

Now we have just learned how metadata and default attribute member variable values in the user object come from.

Next, the dynamic language features are related. Let's look at how to use the user object to operate the data attributes dynamically.

There is an email field in the users table in the database. Now we want to assign a value to the email attribute of the newly created user object, as shown below:

$ User-> email = 'iefreer @ hotmail.com ';

If it is a traditional object-oriented language such as C ++/Java, a compilation error is reported because the user class does not define the email member variable.

For PhP5, because the language supports dynamic features (MAGIC functions), there is no problem with such calls. Let's see how it is implemented internally.

As mentioned in my previous PHP language Dynamic Features article, setting an object's non-existent attribute triggers the _ set magic function of this object:

/** * PHP setter magic method. * This method is overridden so that AR attributes can be accessed like properties. * @param string $name property name * @param mixed $value property value */public function __set($name,$value){if($this->setAttribute($name,$value)===false){if(isset($this->getMetaData()->relations[$name]))$this->_related[$name]=$value;elseparent::__set($name,$value);}}

In the above Code, the setattribute function will add the email to the member variable $ _ attributes, which is an array type member variable. That is, $ _ attributes acts as the dynamic manager of the data table attribute corresponding to the model.

Let's look at the statement for reading the attributes of the user object:

$ Email = $ user-> email;

Similarly, this statement triggers the _ get magic function of the cactiverecord class and returns the value of the corresponding attribute in the $ _ attributes array.

By iefreer

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.