You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
243 lines
9.3 KiB
PHTML
243 lines
9.3 KiB
PHTML
5 years ago
|
<?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 = $key.'Model';
|
||
|
$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;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 检查条件中的视图字段
|
||
|
* @access protected
|
||
|
* @param mixed $data 条件表达式
|
||
|
* @return array
|
||
|
*/
|
||
|
protected function checkCondition($where) {
|
||
|
if(is_array($where)) {
|
||
|
$view = array();
|
||
|
// 检查视图字段
|
||
|
foreach ($this->viewFields as $key=>$val){
|
||
|
$k = isset($val['_as'])?$val['_as']:$key;
|
||
|
$val = $this->_checkFields($key,$val);
|
||
|
foreach ($where as $name=>$value){
|
||
|
if(false !== $field = array_search($name,$val,true)) {
|
||
|
// 存在视图字段
|
||
|
$_key = is_numeric($field)? $k.'.'.$name : $k.'.'.$field;
|
||
|
$view[$_key] = $value;
|
||
|
unset($where[$name]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
$where = array_merge($where,$view);
|
||
|
}
|
||
|
return $where;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 检查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;
|
||
|
}
|
||
|
}
|