1. 程式人生 > >解決TP3.2中新增資料庫表字段後查詢無效的問題

解決TP3.2中新增資料庫表字段後查詢無效的問題

前段時間在TP3.2中做開發時碰到一個詭異的問題,資料庫的某個表新增了一個欄位,然後在查詢條件中新增了這部分條件程式碼,如圖: 


奇怪的是,重新整理頁面之後這段程式碼似乎對查詢結果沒有任何影響,後來經過同事提醒,才知道資料庫結構變動之後要主動清除TP框架的快取。問題雖然得到了解決,但是我仍心有餘悸:TP3.2究竟對資料庫查詢做了什麼,為什麼快取會對實時查詢產生影響?

經過仔細排查,最後我們跟蹤到了這裡:

public function select($options=array()) {
        $pk   =  $this->getPk();
        if(is_string($options) || is_numeric($options)) {
            // 根據主鍵查詢
            if(strpos($options,',')) {
                $where[$pk]     =  array('IN',$options);
            }else{
                $where[$pk]     =  $options;
            }
            $options            =  array();
            $options['where']   =  $where;
        }elseif (is_array($options) && (count($options) > 0) && is_array($pk)) {
            // 根據複合主鍵查詢
            $count = 0;
            foreach (array_keys($options) as $key) {
                if (is_int($key)) $count++; 
            } 
            if ($count == count($pk)) {
                $i = 0;
                foreach ($pk as $field) {
                    $where[$field] = $options[$i];
                    unset($options[$i++]);
                }
                $options['where']  =  $where;
            } else {
                return false;
            }
        } elseif(false === $options){ // 用於子查詢 不查詢只返回SQL
        $options['fetch_sql'] = true;
        }
        // 分析表示式
        $options    =  $this->_parseOptions($options);... 在_parseOptions方法中:
protected function _parseOptions($options=array()) {
        if(is_array($options))
            $options =  array_merge($this->options,$options);        if(!isset($options['table'])){
            // 自動獲取表名
            $options['table']   =   $this->getTableName();
            $fields             =   $this->fields;
        }else{
            // 指定資料表 則重新獲取欄位列表 但不支援型別檢測
            $fields             =   $this->getDbFields();
        }        // 資料表別名
        if(!empty($options['alias'])) {
            $options['table']  .=   ' '.$options['alias'];
        }
        // 記錄操作的模型名稱
        $options['model']       =   $this->name;        // 欄位型別驗證
        if(isset($options['where']) && is_array($options['where']) && !empty($fields) && !isset($options['join'])) {
            // 對陣列查詢條件進行欄位型別檢查
            foreach ($options['where'] as $key=>$val){
                $key            =   trim($key);
                if(in_array($key,$fields,true)){
                    if(is_scalar($val)) {
                        $this->_parseType($options['where'],$key);
                    }
                }elseif(!is_numeric($key) && '_' != substr($key,0,1) && false === strpos($key,'.') && false === strpos($key,'(') && false === strpos($key,'|') && false === strpos($key,'&')){
                    if(!empty($this->options['strict'])){
                        E(L('_ERROR_QUERY_EXPRESS_').':['.$key.'=>'.$val.']');
                    } 
                    unset($options['where'][$key]);
                }
            }
        }
... 
在這部分程式中,我們發現,傳入的一部分查詢條件被過濾了( unset($options['where'][$key])),原因是我們新增的欄位被儲存到$options['where']的key中,但是這個key並沒有存在於$fields中。接下來我們來追蹤$options的來源: 
我們看到:$options陣列的內容是在執行select操作時執行的。那麼$fields這個變數的內容又是在哪兒初始化的呢?


從上圖可知,程式在例項化資料庫時,就已經初始化了$fields變數。到這裡,所有的謎團都解開了。TP會將資料庫的表字段資訊快取在檔案中,然後當PHP程式執行到相關的資料庫操作時,會直接從快取檔案中獲取相關的表字段資訊,然後進行驗證和檢查。由於我們新增了欄位,卻沒有更新快取,新增加的部分查詢條件自然就"丟失"了。 

解決方式:刪除 runtime/Data/_fields/xxxx    中對應的資料表的檔案就行了

轉自:http://codespeaking.com/?post=325



相關推薦

解決TP3.2新增資料庫表字查詢無效的問題

前段時間在TP3.2中做開發時碰到一個詭異的問題,資料庫的某個表新增了一個欄位,然後在查詢條件中新增了這部分條件程式碼,如圖: 奇怪的是,重新整理頁面之後這段程式碼似乎對查詢結果沒有任何影響,後來經過同事提醒,才知道資料庫結構變動之後要主動清除TP框架的快取。問題雖然得到了解

tp3.2index.php配置.htaccess無法去掉index.php的解決方案

rewrite inf path php access acc tp3.2 php配置 index.php tp3.2.3在php5.6版本和版本以上的確會出現不能隱藏index.php大多數夥伴只看文檔裏面提供的方法產生了誤導。官方文檔中.htaccess裏面Rewrit

(學習資料庫表字命名規範

原文連結:https://www.cnblogs.com/pangguoming/p/7126512.html   一、資料庫命名規範 採用26個英文字母(區分大小寫)和0-9的自然數(經常不需要)加上下劃線'_'組成,命名簡潔明確,多個單詞用下劃線'_'分隔,一個專案一個數據

MyBatis由淺入深學習總結之二:MyBatis解決Java實體類和資料庫表字不一致方法總結

在此,首先說明一點任何永續性框架都需要解決一個問題,那就是Java實體類的欄位一般來說基本上會與資料庫表中欄位不一致,那麼它們是如何解決的呢?咱們以Hibernate和SpringJDBC為例說明一下; 1、Hibernate中一般通過XML對映和註解的方式解決不一致問題,

Mybatis解決資料庫表字與實體類不一致的解決方法

解決方法一:通過在查詢sql語句中定義欄位名的別名,讓欄位名的別名和實體類的屬性名一致,這樣就可以使表的欄位名和實體類的屬性名一一對應上了,這種方式時通過在sql語句中定義別名來解決欄位名和屬性名的對映關係的。 解決方法二:通過<resultMap>來對映欄位名和實體類屬性名一

oracle 資料庫表字新增、修改、刪除等DDL操作

oracle 資料庫表字段新增、修改、刪除等操作 1. 建立表 -- Create table create table TB_PERMISSION_ORGANIZATION ( id VARCHAR2(150) not null, parent_id

tp3.2excel表格資料匯入資料庫

第一步:將壓縮包PHPExcel解壓後放到./ThinkPHP/Library/Vendor目錄下面。 第二步:控制器裡面的方法:         public function addActivitydo(){             if (!empty($_FILE

Oracle12.2新增的分區功能

功能 防止 新功能 時間 如果 針對 alt 關鍵字 只讀 Oracle 12.2已經發布一段時間,公網上也可以下載試用。針對12.2,partitioning(分區)也有了不少增強。自動列表分區多字段列表分區只讀分區分區維護時允許過濾在線轉換非分區表為分區表帶分區的外部

獲取資料庫表字名,長度,型別,備註等資訊

獲取資料庫表的所有欄位的資訊 select * from information_schema.columns where table_name = '表名' 獲取資料庫表字段名,長度,型別,備註,是否能空 select column_name,COLUMN_TYPE,

mybaits(查詢與別名、日誌框架顯示sql語句、物件屬性和資料庫表字不匹配resultMap使用、mysql資料查詢分頁、執行sql和儲存過程、動態SQL語句)

主要是各種配置檔案,建議把整個專案搬到自己電腦上慢慢看。 建立maven專案 首先是各種配置檔案: pom.xml: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://m

TP3.2 驗證碼類使用流程

1.在Index控制器中,建立產生驗證碼的方法: function verify(){ //1.例項化驗證碼類 $config = array( 'useImgBg' => false, // 使用背景圖片 'fon

TP3.2PHPExcel獲取指定單元格內容的簡單應用

public function excel($x = '1',$y = 'C',$sheet = '1') //輸出表格指定位置資訊 $X 行 $y 列 $sheet 表格頁數(0開始) { date_default_timezone_s

Android-工作總結-LX-2018-08-20-判斷資料庫表字是否為空

問題的因素: 除錯了一上午,我要判斷資料庫表的name欄位是否為空,使用了TextUtils.isEmpty(nameStr);來判斷name欄位是否為空,明明資料庫是沒有值,卻一直顯示有值,然後還去質疑TextUtils.isEmpty(nameStr);,最後才發現是我存入資料的時候有問題 不能 nam

mysql資料庫表字增刪改查及索引的增刪改查

#增加欄位 ALTER TABLE `表名` ADD COLUMN `欄位名` VARCHAR(11) NULL DEFAULT '' comment '測試表id' AFTER `login_cou

tp5代替tp3.2的一些方法

U方法 U方法是TP中的生成路由的內建方法,現在這個方法可以完全使用url方法替換 I方法 之前的TP有個I方法用來接收請求引數,目前可以使用input方法替代 C方法 c方法被config方法代替 U方法是TP中的生成路由的內建方法,現在這個方法可以完全使用url方法替換

mysql匯出部分(指定)資料庫表字

由於業務需求,需要匯出某個表中的部分欄位資訊 之前匯出資料庫表一直使用mysqldump命令,例如: mysqldump -hIP -uroot -P3306 -p 庫 表 > 名字.sql 但是如果匯出指定欄位的話,這個命令就不好用了,網上一般都介紹可以增加引數,如

使用cakephp 1.2新增的訪問控制組件(acl)

            #modules 由我手動建立.aco要有個專門的controller進行管理,放在這裡為了更簡單的說明如何建立aco                        $aco = $this->Acl->Aco;            # 模組ACO,包括網站的各個部分,一

解決在.gitignore新增忽略檔案,忽略不生效的方法

由於一些配置資訊的私密性,不方便提交配置資訊檔案。於是在.gitignore中新增檔案忽略,但是再次git status檢視提交前的資訊時,配置檔案(config.py)還是跟蹤到了: 後面查閱相關的資料才知道需要進行下面操作 git rm -r --cached . 實際操作如

Java實體類的屬性型別與mysql資料庫表字型別對應表

感謝原文博主https://blog.csdn.net/Hyo555/article/details/81943340 還有些經常用到的mysql語句 -- 新增表結構 DROP TABLE IF EXISTS `servicnn`; CREATE TABLE `servin` ( `id` i

將某個資料庫表字按照自然順序賦值排序

現有一張表space_user,表中有個欄位priority,該欄位的順序是亂的,我想把該欄位重新排序,mysql資料庫的sql語句如下: update space_user target,( select (@rowNO := @rowNo+1) AS rowno,a.*