| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- <?php
- // +----------------------------------------------------------------------
- // | 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 <liu21st@gmail.com>
- // +----------------------------------------------------------------------
- namespace Think\Model;
- use Think\Model;
- /**
- * ThinkPHP视图模型扩展
- */
- class ViewModel extends Model
- {
- protected $viewFields = array();
- /**
- * 自动检测数据表信息
- * @access protected
- * @return void
- */
- protected function _checkTableInfo()
- {}
- /**
- * 得到完整的数据表名
- * @access public
- * @return string
- */
- public function getTableName()
- {
- if (empty($this->trueTableName)) {
- $tableName = '';
- foreach ($this->viewFields as $key => $view) {
- // 获取数据表名称
- if (isset($view['_table'])) {
- // 2011/10/17 添加实际表名定义支持 可以实现同一个表的视图
- $tableName .= $view['_table'];
- $prefix = $this->tablePrefix;
- $tableName = preg_replace_callback("/__([A-Z_-]+)__/sU", function ($match) use ($prefix) {return $prefix . strtolower($match[1]);}, $tableName);
- } else {
- $class = parse_res_name($key, C('DEFAULT_M_LAYER'));
- $Model = class_exists($class) ? new $class() : M($key);
- $tableName .= $Model->getTableName();
- }
- // 表别名定义
- $tableName .= !empty($view['_as']) ? ' ' . $view['_as'] : ' ' . $key;
- // 支持ON 条件定义
- $tableName .= !empty($view['_on']) ? ' ON ' . $view['_on'] : '';
- // 指定JOIN类型 例如 RIGHT INNER LEFT 下一个表有效
- $type = !empty($view['_type']) ? $view['_type'] : '';
- $tableName .= ' ' . strtoupper($type) . ' JOIN ';
- $len = strlen($type . '_JOIN ');
- }
- $tableName = substr($tableName, 0, -$len);
- $this->trueTableName = $tableName;
- }
- return $this->trueTableName;
- }
- /**
- * 表达式过滤方法
- * @access protected
- * @param string $options 表达式
- * @return void
- */
- protected function _options_filter(&$options)
- {
- if (isset($options['field'])) {
- $options['field'] = $this->checkFields($options['field']);
- } else {
- $options['field'] = $this->checkFields();
- }
- if (isset($options['group'])) {
- $options['group'] = $this->checkGroup($options['group']);
- }
- if (isset($options['where'])) {
- $options['where'] = $this->checkCondition($options['where']);
- }
- if (isset($options['order'])) {
- $options['order'] = $this->checkOrder($options['order']);
- }
- }
- /**
- * 检查是否定义了所有字段
- * @access protected
- * @param string $name 模型名称
- * @param array $fields 字段数组
- * @return array
- */
- private function _checkFields($name, $fields)
- {
- if (false !== $pos = array_search('*', $fields)) {
- // 定义所有字段
- $fields = array_merge($fields, M($name)->getDbFields());
- unset($fields[$pos]);
- }
- return $fields;
- }
- /**
- * 检查条件中的视图字段
- * @param $where 条件表达式
- * @return array
- */
- protected function checkCondition($where)
- {
- if (is_array($where)) {
- $fields = $field_map_table = array();
- foreach ($this->viewFields as $key => $val) {
- $table_alias = isset($val['_as']) ? $val['_as'] : $key;
- $val = $this->_checkFields($key, $val);
- foreach ($val as $as_name => $v) {
- if (is_numeric($as_name)) {
- $fields[] = $v; //所有表字段集合
- $field_map_table[] = $table_alias; //所有表字段对应表名集合
- } else {
- $fields[$as_name] = $v;
- $field_map_table[$as_name] = $table_alias;
- }
- }
- }
- $where = $this->_parseWhere($where, $fields, $field_map_table);
- }
- return $where;
- }
- /**
- * 解析where表达式
- * @param $where
- * @param $fields
- * @param $field_map_table
- * @return array
- */
- private function _parseWhere($where, $fields, $field_map_table)
- {
- $view = array();
- foreach ($where as $name => $val) {
- if ('_complex' == $name) {
- //复合查询
- foreach ($val as $k => $v) {
- if (false === strpos(substr($k, 0, 1), '_')) {
- if (false !== $field = array_search($k, $fields, true)) { // 存在视图字段
- $k = is_numeric($field) ? $field_map_table[$field] . '.' . $k : $field_map_table[$field] . '.' . $field; //字段别名
- }
- } else if (is_array($v)) {
- //数组复合查询
- $v = $this->_parseWhere($val[$k], $fields, $field_map_table);
- }
- $view[$name][$k] = $v;
- }
- } else {
- if (strpos($name, '|')) {
- //name|title快捷查询
- $arr = explode('|', $name);
- foreach ($arr as $k => $v) {
- if (false !== $field = array_search($v, $fields, true)) {
- $arr[$k] = is_numeric($field) ? $field_map_table[$field] . '.' . $v : $field_map_table[$field] . '.' . $field;
- }
- }
- $view[implode('|', $arr)] = $val;
- } else if (strpos($name, '&')) {
- //name&title快捷查询
- $arr = explode('&', $name);
- foreach ($arr as $k => $v) {
- if (false !== $field = array_search($v, $fields, true)) {
- $arr[$k] = is_numeric($field) ? $field_map_table[$field] . '.' . $v : $field_map_table[$field] . '.' . $field;
- }
- }
- $view[implode('&', $arr)] = $val;
- } else {
- if (false !== $field = array_search($name, $fields, true)) {
- $name = is_numeric($field) ? $field_map_table[$field] . '.' . $name : $field_map_table[$field] . '.' . $field;
- }
- $view[$name] = $val;
- }
- }
- }
- return $view;
- }
- /**
- * 检查Order表达式中的视图字段
- * @access protected
- * @param string $order 字段
- * @return string
- */
- protected function checkOrder($order = '')
- {
- if (is_string($order) && !empty($order)) {
- $orders = explode(',', $order);
- $_order = array();
- foreach ($orders as $order) {
- $array = explode(' ', trim($order));
- $field = $array[0];
- $sort = isset($array[1]) ? $array[1] : 'ASC';
- // 解析成视图字段
- foreach ($this->viewFields as $name => $val) {
- $k = isset($val['_as']) ? $val['_as'] : $name;
- $val = $this->_checkFields($name, $val);
- if (false !== $_field = array_search($field, $val, true)) {
- // 存在视图字段
- $field = is_numeric($_field) ? $k . '.' . $field : $k . '.' . $_field;
- break;
- }
- }
- $_order[] = $field . ' ' . $sort;
- }
- $order = implode(',', $_order);
- }
- return $order;
- }
- /**
- * 检查Group表达式中的视图字段
- * @access protected
- * @param string $group 字段
- * @return string
- */
- protected function checkGroup($group = '')
- {
- if (!empty($group)) {
- $groups = explode(',', $group);
- $_group = array();
- foreach ($groups as $field) {
- // 解析成视图字段
- foreach ($this->viewFields as $name => $val) {
- $k = isset($val['_as']) ? $val['_as'] : $name;
- $val = $this->_checkFields($name, $val);
- if (false !== $_field = array_search($field, $val, true)) {
- // 存在视图字段
- $field = is_numeric($_field) ? $k . '.' . $field : $k . '.' . $_field;
- break;
- }
- }
- $_group[] = $field;
- }
- $group = implode(',', $_group);
- }
- return $group;
- }
- /**
- * 检查fields表达式中的视图字段
- * @access protected
- * @param string $fields 字段
- * @return string
- */
- protected function checkFields($fields = '')
- {
- if (empty($fields) || '*' == $fields) {
- // 获取全部视图字段
- $fields = array();
- foreach ($this->viewFields as $name => $val) {
- $k = isset($val['_as']) ? $val['_as'] : $name;
- $val = $this->_checkFields($name, $val);
- foreach ($val as $key => $field) {
- if (is_numeric($key)) {
- $fields[] = $k . '.' . $field . ' AS ' . $field;
- } elseif ('_' != substr($key, 0, 1)) {
- // 以_开头的为特殊定义
- if (false !== strpos($key, '*') || false !== strpos($key, '(') || false !== strpos($key, '.')) {
- //如果包含* 或者 使用了sql方法 则不再添加前面的表名
- $fields[] = $key . ' AS ' . $field;
- } else {
- $fields[] = $k . '.' . $key . ' AS ' . $field;
- }
- }
- }
- }
- $fields = implode(',', $fields);
- } else {
- if (!is_array($fields)) {
- $fields = explode(',', $fields);
- }
- // 解析成视图字段
- $array = array();
- foreach ($fields as $key => $field) {
- if (strpos($field, '(') || strpos(strtolower($field), ' as ')) {
- // 使用了函数或者别名
- $array[] = $field;
- unset($fields[$key]);
- }
- }
- foreach ($this->viewFields as $name => $val) {
- $k = isset($val['_as']) ? $val['_as'] : $name;
- $val = $this->_checkFields($name, $val);
- foreach ($fields as $key => $field) {
- if (false !== $_field = array_search($field, $val, true)) {
- // 存在视图字段
- if (is_numeric($_field)) {
- $array[] = $k . '.' . $field . ' AS ' . $field;
- } elseif ('_' != substr($_field, 0, 1)) {
- if (false !== strpos($_field, '*') || false !== strpos($_field, '(') || false !== strpos($_field, '.'))
- //如果包含* 或者 使用了sql方法 则不再添加前面的表名
- {
- $array[] = $_field . ' AS ' . $field;
- } else {
- $array[] = $k . '.' . $_field . ' AS ' . $field;
- }
- }
- }
- }
- }
- $fields = implode(',', $array);
- }
- return $fields;
- }
- }
|