1. 程式人生 > >ThinkPHP3.2.5的Model基類,有些文件中沒提到的方法,可以經常看看。

ThinkPHP3.2.5的Model基類,有些文件中沒提到的方法,可以經常看看。

// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: liu21st <[email protected]> // +---------------------------------------------------------------------- namespace Think; /** * ThinkPHP Model模型類 * 實現了ORM和ActiveRecords模式 */
class Model { // 操作狀態 const MODEL_INSERT = 1; // 插入模型資料 const MODEL_UPDATE = 2; // 更新模型資料 const MODEL_BOTH = 3; // 包含上面兩種方式 const MUST_VALIDATE = 1; // 必須驗證 const EXISTS_VALIDATE = 0; // 表單存在欄位則驗證 const VALUE_VALIDATE = 2; // 表單值不為空則驗證 // 當前資料庫操作物件 protected $db
= null; // 資料庫物件池 private $_db = array(); // 主鍵名稱 protected $pk = 'id'; // 主鍵是否自動增長 protected $autoinc = false; // 資料表字首 protected $tablePrefix = null; // 模型名稱 protected $name = ''; // 資料庫名稱 protected $dbName = ''; //資料庫配置 protected $connection = ''; // 資料表名(不包含表字首) protected $tableName = ''; // 實際資料表名(包含表字首) protected $trueTableName = ''; // 最近錯誤資訊 protected $error = ''; // 欄位資訊 protected $fields = array(); // 資料資訊 protected $data = array(); // 查詢表示式引數 protected $options = array(); protected $_validate = array(); // 自動驗證定義 protected $_auto = array(); // 自動完成定義 protected $_map = array(); // 欄位對映定義 protected $_scope = array(); // 命名範圍定義 // 是否自動檢測資料表字段資訊 protected $autoCheckFields = true; // 是否批處理驗證 protected $patchValidate = false; // 鏈操作方法列表 protected $methods = array('strict', 'order', 'alias', 'having', 'group', 'lock', 'distinct', 'auto', 'filter', 'validate', 'result', 'token', 'index', 'force', 'master'); /** * 架構函式 * 取得DB類的例項物件 欄位檢查 * @access public * @param string $name 模型名稱 * @param string $tablePrefix 表字首 * @param mixed $connection 資料庫連線資訊 */ public function __construct($name = '', $tablePrefix = '', $connection = '') { // 模型初始化 $this->_initialize(); // 獲取模型名稱 if (!empty($name)) { if (strpos($name, '.')) { // 支援 資料庫名.模型名的 定義 list($this->dbName, $this->name) = explode('.', $name); } else { $this->name = $name; } } elseif (empty($this->name)) { $this->name = $this->getModelName(); } // 設定表字首 if (is_null($tablePrefix)) { // 字首為Null表示沒有字首 $this->tablePrefix = ''; } elseif ('' != $tablePrefix) { $this->tablePrefix = $tablePrefix; } elseif (!isset($this->tablePrefix)) { $this->tablePrefix = !empty($this->connection) && !is_null(C($this->connection . '.DB_PREFIX')) ? C($this->connection . '.DB_PREFIX') : C('DB_PREFIX'); } // 資料庫初始化操作 // 獲取資料庫操作物件 // 當前模型有獨立的資料庫連線資訊 $this->db(0, empty($this->connection) ? $connection : $this->connection, true); } /** * 自動檢測資料表資訊 * @access protected * @return void */ protected function _checkTableInfo() { // 如果不是Model類 自動記錄資料表資訊 // 只在第一次執行記錄 if (empty($this->fields)) { // 如果資料表字段沒有定義則自動獲取 if (C('DB_FIELDS_CACHE')) { $fields = F('_fields/' . strtolower($this->getTableName())); if ($fields) { $this->fields = $fields; if (!empty($fields['_pk'])) { $this->pk = $fields['_pk']; } return; } } // 每次都會讀取資料表資訊 $this->flush(); } } /** * 獲取欄位資訊並快取 * @access public * @return void */ public function flush() { // 快取不存在則查詢資料表資訊 $this->db->setModel($this->name); $tableName = $this->getTableName(); $fields = $this->db->getFields($tableName); if (!$fields) { // 無法獲取欄位資訊 return false; } $this->fields = array_keys($fields); unset($this->fields['_pk']); foreach ($fields as $key => $val) { // 記錄欄位型別 $type[$key] = $val['type']; if ($val['primary']) { // 增加複合主鍵支援 if (isset($this->fields['_pk']) && null != $this->fields['_pk']) { if (is_string($this->fields['_pk'])) { $this->pk = array($this->fields['_pk']); $this->fields['_pk'] = $this->pk; } $this->pk[] = $key; $this->fields['_pk'][] = $key; } else { $this->pk = $key; $this->fields['_pk'] = $key; } if ($val['autoinc']) { $this->autoinc = true; } } } // 記錄欄位型別資訊 $this->fields['_type'] = $type; // 2008-3-7 增加快取開關控制 if (C('DB_FIELDS_CACHE')) { // 永久快取資料表資訊 F('_fields/' . strtolower($tableName), $this->fields); } } /** * 設定資料物件的值 * @access public * @param string $name 名稱 * @param mixed $value 值 * @return void */ public function __set($name, $value) { // 設定資料物件屬性 $this->data[$name] = $value; } /** * 獲取資料物件的值 * @access public * @param string $name 名稱 * @return mixed */ public function __get($name) { return isset($this->data[$name]) ? $this->data[$name] : null; } /** * 檢測資料物件的值 * @access public * @param string $name 名稱 * @return boolean */ public function __isset($name) { return isset($this->data[$name]); } /** * 銷燬資料物件的值 * @access public * @param string $name 名稱 * @return void */ public function __unset($name) { unset($this->data[$name]); } /** * 利用__call方法實現一些特殊的Model方法 * @access public * @param string $method 方法名稱 * @param array $args 呼叫引數 * @return mixed */ public function __call($method, $args) { if (in_array(strtolower($method), $this->methods, true)) { // 連貫操作的實現 $this->options[strtolower($method)] = $args[0]; return $this; } elseif (in_array(strtolower($method), array('count', 'sum', 'min', 'max', 'avg'), true)) { // 統計查詢的實現 $field = isset($args[0]) ? $args[0] : '*'; return $this->getField(strtoupper($method) . '(' . $this->db->parseKey($field, true) . ') AS tp_' . $method); } elseif (strtolower(substr($method, 0, 5)) == 'getby') { // 根據某個欄位獲取記錄 $field = parse_name(substr($method, 5)); $where[$field] = $args[0]; return $this->where($where)->find(); } elseif (strtolower(substr($method, 0, 10)) == 'getfieldby') { // 根據某個欄位獲取記錄的某個值 $name = parse_name(substr($method, 10)); $where[$name] = $args[0]; return $this->where($where)->getField($args[1]); } elseif (isset($this->_scope[$method])) { // 命名範圍的單獨呼叫支援 return $this->scope($method, $args[0]); } else { E(__CLASS__ . ':' . $method . L('_METHOD_NOT_EXIST_')); return; } } // 回撥方法 初始化模型 protected function _initialize() {} /** * 對儲存到資料庫的資料進行處理 * @access protected * @param mixed $data 要操作的資料 * @return boolean */ protected function _facade($data) { // 檢查資料欄位合法性 if (!empty($this->fields)) { if (!empty($this->options['field'])) { $fields = $this->options['field']; unset($this->options['field']); if (is_string($fields)) { $fields = explode(',', $fields); } } else { $fields = $this->fields; } foreach ($data as $key => $val) { if (!in_array($key, $fields, true)) { if (!empty($this->options['strict'])) { E(L('_DATA_TYPE_INVALID_') . ':[' . $key . '=>' . $val . ']'); } unset($data[$key]); } elseif (is_scalar($val)) { // 欄位型別檢查 和 強制轉換 $this->_parseType($data, $key); } } } // 安全過濾 if (!empty($this->options['filter'])) { $data = array_map($this->options['filter'], $data); unset($this->options['filter']); } $this->_before_write($data); return $data; } // 寫入資料前的回撥方法 包括新增和更新 protect