Yii學習筆記:實現相似於ThinkPHP的模型字段映射,字段別名

在TP中,咱們只要在模型類中定義一個 php


protected $_map = array(
        'name' =>'username', // 把表單中name映射到數據表的username字段
        'mail'  =>'email', // 把表單中的mail映射到數據表的email字段
    );



這樣,咱們前端模板中使用 <input type=text name="name"/>


在模型收集表單數據時會自動將值同時映射到username字段上。 前端

好處是避免數據庫字段直接暴露。 web

但很遺憾,我在學習Yii過程當中沒有找到相似的機制,而Yii的類庫不少,我又不敢貿然本身擴展,總以爲在某個角落裏有某個類可能已經提供瞭解決方案,怕本身作重複無心義之舉。 數據庫

通過一系列的思想鬥爭,樓主仍是決定本身動手啦。。 post

方法很簡單,請先看代碼: 學習


<?php
class CustomModel extends CActiveRecord {
    //定義所須要收集的屬性
    public $username;
    public $email;
    public $passwd;
    public $password;
    public $password1;
    
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }
 
    public function tableName()
    {
        return '{{custom}}';
    }
    
    public function rules(){
        return array(
            array("username,password,email,password1","safe")
        );
    }
    //字段映射配置
    protected $_alias_ = array(
        "passwd" => "password"
    );
    //經過引用傳遞處理映射
    protected function afterConstruct(){
        parent::afterConstruct();
        //字段映射處理
        if(!empty($this->_alias_)){
            foreach($this->_alias_ as $a => $b){
                if(property_exists($this,$a) && property_exists($this,$b)){
                    $this->$a = &$this->$b;
                }
            }
        }
    }
}



模板:



<?php defined("APP_NAME") or exit;?>
<form action="" method="post">
    <table>
        <tr>
            <th>用戶名:</th>
            <td><input type="text" name="username" placeholder="請設置您的帳號名" value=""/></td>
        </tr>
        <tr>
            <th>郵箱:</th>
            <td><input type="email" name="email" placeholder="example@website" value=""/></td>
        </tr>
        <tr>
            <th>密碼:</th>
            <td><input type="password" name="password" value=""/></td>
        </tr>
        <tr>
            <th>重複密碼:</th>
            <td><input type="password" name="password1" value=""/></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form>



能夠發現,我在表單中使用了password字段名做爲密碼,可是我數據庫中的字段是passwd,若是直接這樣收集表單,是沒法將密碼數據入庫的。


因此我在模型類中定義了1個方法: this

afterConstruct()
一個屬性
protected $_alias_
咱們在$_alias_這個屬性裏面定義映射,好比我定義了 "passwd"=>"password"的映射。

afterConstruct()這個方法是在你實例化模型類以後執行的,能夠當作在 $model = new CustomModel()的時候觸發,這裏面主要作了一個工做,就是檢測$_alias_有沒有定義映射,若是有的話,咱們使用php的引用傳遞特性來使兩個字段指向同一個值。 spa

最後,爲了能夠全局使用,建議在components/目錄下創建一個 CommonModel類,將afterConstruct()方法放在這個類裏,其餘模型繼承這個類就能夠了,這樣只要在各自的模型中定義_alias_屬性便可。 code

/////////基於事件的處理方法 component

<?php
class CommonAR extends CActiveRecord{
    function init(){
        $this->onAfterConstruct = array($this,"autoMap");
    }
    //字段映射配置
    protected $_alias_ = array(
    );
    
    function autoMap($event){
        //字段映射處理
        if(!empty($this->_alias_)){
            foreach($this->_alias_ as $a => $b){
                if(property_exists($this,$a) && property_exists($this,$b)){
                    $this->$a = &$this->$b;
                }
            }
        }
    }
}



假設在components/下建立一個 CommonAR類,咱們在init()方法中註冊一個事件
$this->onAfterConstruct = array($this,"autoMap");
對應的事件方法就是類裏面的autoMap()

而後建立具體模型的時候繼承CommonAR類,定義$_alias_便可。

相關文章
相關標籤/搜索