溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

【ThinkPHP】關(guān)于ThinkPHP關(guān)聯(lián)模型和視圖模型的一些心得

發(fā)布時(shí)間:2020-07-20 11:29:19 來源:網(wǎng)絡(luò) 閱讀:2965 作者:AndyMac 欄目:web開發(fā)

    視圖模型更加類似一張表虛擬的表,視圖包含一系列帶有名稱的列和行數(shù)據(jù)。但是,視圖并不在數(shù)據(jù)庫中以存儲(chǔ)的數(shù)據(jù)值集形式存在。行和列數(shù)據(jù)來自由定義視圖的查詢所引用的表,并且在引用視圖時(shí)動(dòng)態(tài)生成。對(duì)其中所引用的基礎(chǔ)表來說,視圖的作用類似于篩選,這是ThinkPHP手冊(cè)上的說法

    其實(shí)說白了,視圖模型就是mysql多表查詢而已,視圖模型不支持多表更新,刪除


    而關(guān)聯(lián)模型是多個(gè)表查詢以后的結(jié)果組合,會(huì)多次查詢mysql,(在執(zhí)行完主表查詢以后,會(huì)有個(gè)_after_select)之類的操作,然后組合結(jié)果集。在一些情況下,關(guān)聯(lián)模型的查詢還是比較不錯(cuò)的。

    以下是個(gè)人使用ThinkPHP的關(guān)聯(lián)模型和視圖模型的一些心得和比較

    一:性能方面

      視圖模型,說白了就是關(guān)聯(lián)查詢,一次查詢多表

      關(guān)聯(lián)模型,每次查詢一張表,多次查詢,然后組合結(jié)果集(插入,更新,刪除也是一樣的。)  

      個(gè)人覺得視圖模型性能會(huì)好一些(不一定全部都是,沒有具體測(cè)試過)

    二:查詢

      如果是查詢的話,強(qiáng)烈建議使用視圖模型來做,寫法簡(jiǎn)單,容易理解和更改,而關(guān)聯(lián)模型的定義方式太多,而且結(jié)果集的處理,調(diào)試,都不如視圖模型要方便。

    三:插入,更新,刪除

      視圖模型不支持,關(guān)聯(lián)模型支持,但是在插入,更新的時(shí)候,不能使用Model的create方法,還有自動(dòng)完成,自動(dòng)更新都失效了,我自己重寫了一個(gè)create,給大家一些提示,可以自己按照需要更改。

   

/**
     * 重載create方法,不過濾字段,并且生成需要數(shù)據(jù)
     */
    function create($data = '', $type = '') {
        // 如果沒有傳值默認(rèn)取POST數(shù)據(jù)
        if (empty($data)) {
            $data = $_POST;
        } elseif (is_object($data)) {
            $data = get_object_vars($data);
        }
        // 驗(yàn)證數(shù)據(jù)
        if (empty($data) || !is_array($data)) {
            $this->error = L('_DATA_TYPE_INVALID_');
            return false;
        }
        // 狀態(tài)
        $type = $type ? $type : (!empty($data[$this->getPk() ]) ? self::MODEL_UPDATE : self::MODEL_INSERT);
        // 數(shù)據(jù)自動(dòng)驗(yàn)證
        if (!$this->autoValidation($data, $type)) return false;
        // 表單令牌驗(yàn)證
        if (!$this->autoCheckToken($data)) {
            $this->error = L('_TOKEN_ERROR_');
            return false;
        }
        // 驗(yàn)證完成生成數(shù)據(jù)對(duì)象
        if ($this->autoCheckFields) { // 開啟字段檢測(cè) 則過濾非法字段數(shù)據(jù)
            $fields = $this->getDbFields();
            foreach ($data as $key => $val) {
                if (MAGIC_QUOTES_GPC && is_string($val)) {
                    $data[$key] = stripslashes($val);
                }
            }
        }
        // 創(chuàng)建完成對(duì)數(shù)據(jù)進(jìn)行自動(dòng)處理
        $data=$this->autoOperation($data, $type);
        $data=$this->createData($data);
        // 返回創(chuàng)建的數(shù)據(jù)以供其他調(diào)用
        return $data;
    }

    /**
     * 自動(dòng)表單處理
     * @access public
     * @param array $data 創(chuàng)建數(shù)據(jù)
     * @param string $type 創(chuàng)建類型
     * @return mixed
     */
    private function autoOperation($data, $type) {
        if (!empty($this->options['auto'])) {
            $_auto = $this->options['auto'];
            unset($this->options['auto']);
        } elseif (!empty($this->_auto)) {
            $_auto = $this->_auto;
        }
        // 自動(dòng)填充
        if (isset($_auto)) {
            foreach ($_auto as $auto) {
                // 填充因子定義格式
                // array('field','填充內(nèi)容','填充條件','附加規(guī)則',[額外參數(shù)])
                if (empty($auto[2])) $auto[2] = self::MODEL_INSERT; // 默認(rèn)為新增的時(shí)候自動(dòng)填充
                if ($type == $auto[2] || $auto[2] == self::MODEL_BOTH) {
                    switch (trim($auto[3])) {
                        case 'function': //  使用函數(shù)進(jìn)行填充 字段的值作為參數(shù)
                        case 'callback': // 使用回調(diào)方法
                            $args = isset($auto[4]) ? (array)$auto[4] : array();
                            if (isset($data[$auto[0]])) {
                                array_unshift($args, $data[$auto[0]]);
                            }
                            if ('function' == $auto[3]) {
                                $data[$auto[0]] = call_user_func_array($auto[1], $args);
                            } else {
                                $data[$auto[0]] = call_user_func_array(array(&$this,
                                    $auto[1]
                                ) , $args);
                            }
                            break;
                        case 'field': // 用其它字段的值進(jìn)行填充
                            $data[$auto[0]] = $data[$auto[1]];
                            break;
                        case 'ignore': // 為空忽略
                            if ('' === $data[$auto[0]]) unset($data[$auto[0]]);
                            break;

                        case 'string':
                        default: // 默認(rèn)作為字符串填充
                            $data[$auto[0]] = $auto[1];
                        }
                        if (false === $data[$auto[0]]) unset($data[$auto[0]]);
                    }
            }
        }
        return $data;
    }
    
    /**
     * 生成關(guān)聯(lián)模型需要的數(shù)據(jù)
     */
    function createData($data) {
        foreach ($data as $k => $v) {
            if (in_array($k, $this->fields)) {
                $data['Article'][$k] = $v;
                unset($data[$k]);
            }
        }
        //刪除多余字段
        unset($data['nid']);
        unset($data['create_date']);
        return $data;
    }


    就是直接復(fù)制的原來的create方法,但是去掉了字段過濾,然后自動(dòng)驗(yàn)證,自動(dòng)完成后,createData方法生成最后的數(shù)據(jù),我覺得官方應(yīng)該修改一下這一塊,就更好了。

    

    其他:因?yàn)槲叶x的插入,更新,刪除,查詢等,都是在CommonAction公共類中,如果有特殊條件要使用關(guān)聯(lián)查詢,那么如果用關(guān)聯(lián)視圖的話,還要改成$model->relation(true)->select()的方式,個(gè)人覺得不是很方便,直接視圖模型就不需要更改了。

    

    調(diào)試:視圖模型會(huì)打印關(guān)聯(lián)查詢的全部sql語句,而關(guān)聯(lián)模型,則只會(huì)打印第一條sql語句(因?yàn)樗麄兪菆?zhí)行多條sql語句)


【ThinkPHP】關(guān)于ThinkPHP關(guān)聯(lián)模型和視圖模型的一些心得

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI