ViewModel.class.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. defined('THINK_PATH') or exit();
  12. /**
  13. * ThinkPHP视图模型扩展
  14. * @category Extend
  15. * @package Extend
  16. * @subpackage Model
  17. * @author liu21st <liu21st@gmail.com>
  18. */
  19. class ViewModel extends Model {
  20. protected $viewFields = array();
  21. /**
  22. * 自动检测数据表信息
  23. * @access protected
  24. * @return void
  25. */
  26. protected function _checkTableInfo() {}
  27. /**
  28. * 得到完整的数据表名
  29. * @access public
  30. * @return string
  31. */
  32. public function getTableName() {
  33. if(empty($this->trueTableName)) {
  34. $tableName = '';
  35. foreach ($this->viewFields as $key=>$view){
  36. // 获取数据表名称
  37. if(isset($view['_table'])) { // 2011/10/17 添加实际表名定义支持 可以实现同一个表的视图
  38. $tableName .= $view['_table'];
  39. }else{
  40. $class = $key.'Model';
  41. $Model = class_exists($class)?new $class():M($key);
  42. $tableName .= $Model->getTableName();
  43. }
  44. // 表别名定义
  45. $tableName .= !empty($view['_as'])?' '.$view['_as']:' '.$key;
  46. // 支持ON 条件定义
  47. $tableName .= !empty($view['_on'])?' ON '.$view['_on']:'';
  48. // 指定JOIN类型 例如 RIGHT INNER LEFT 下一个表有效
  49. $type = !empty($view['_type'])?$view['_type']:'';
  50. $tableName .= ' '.strtoupper($type).' JOIN ';
  51. $len = strlen($type.'_JOIN ');
  52. }
  53. $tableName = substr($tableName,0,-$len);
  54. $this->trueTableName = $tableName;
  55. }
  56. return $this->trueTableName;
  57. }
  58. /**
  59. * 表达式过滤方法
  60. * @access protected
  61. * @param string $options 表达式
  62. * @return void
  63. */
  64. protected function _options_filter(&$options) {
  65. if(isset($options['field']))
  66. $options['field'] = $this->checkFields($options['field']);
  67. else
  68. $options['field'] = $this->checkFields();
  69. if(isset($options['group']))
  70. $options['group'] = $this->checkGroup($options['group']);
  71. if(isset($options['where']))
  72. $options['where'] = $this->checkCondition($options['where']);
  73. if(isset($options['order']))
  74. $options['order'] = $this->checkOrder($options['order']);
  75. }
  76. /**
  77. * 检查是否定义了所有字段
  78. * @access protected
  79. * @param string $name 模型名称
  80. * @param array $fields 字段数组
  81. * @return array
  82. */
  83. private function _checkFields($name,$fields) {
  84. if(false !== $pos = array_search('*',$fields)) {// 定义所有字段
  85. $fields = array_merge($fields,M($name)->getDbFields());
  86. unset($fields[$pos]);
  87. }
  88. return $fields;
  89. }
  90. /**
  91. * 检查条件中的视图字段
  92. * @access protected
  93. * @param mixed $data 条件表达式
  94. * @return array
  95. */
  96. protected function checkCondition($where) {
  97. if(is_array($where)) {
  98. $view = array();
  99. // 检查视图字段
  100. foreach ($this->viewFields as $key=>$val){
  101. $k = isset($val['_as'])?$val['_as']:$key;
  102. $val = $this->_checkFields($key,$val);
  103. foreach ($where as $name=>$value){
  104. if(false !== $field = array_search($name,$val,true)) {
  105. // 存在视图字段
  106. $_key = is_numeric($field)? $k.'.'.$name : $k.'.'.$field;
  107. $view[$_key] = $value;
  108. unset($where[$name]);
  109. }
  110. }
  111. }
  112. $where = array_merge($where,$view);
  113. }
  114. return $where;
  115. }
  116. /**
  117. * 检查Order表达式中的视图字段
  118. * @access protected
  119. * @param string $order 字段
  120. * @return string
  121. */
  122. protected function checkOrder($order='') {
  123. if(is_string($order) && !empty($order)) {
  124. $orders = explode(',',$order);
  125. $_order = array();
  126. foreach ($orders as $order){
  127. $array = explode(' ',$order);
  128. $field = $array[0];
  129. $sort = isset($array[1])?$array[1]:'ASC';
  130. // 解析成视图字段
  131. foreach ($this->viewFields as $name=>$val){
  132. $k = isset($val['_as'])?$val['_as']:$name;
  133. $val = $this->_checkFields($name,$val);
  134. if(false !== $_field = array_search($field,$val,true)) {
  135. // 存在视图字段
  136. $field = is_numeric($_field)?$k.'.'.$field:$k.'.'.$_field;
  137. break;
  138. }
  139. }
  140. $_order[] = $field.' '.$sort;
  141. }
  142. $order = implode(',',$_order);
  143. }
  144. return $order;
  145. }
  146. /**
  147. * 检查Group表达式中的视图字段
  148. * @access protected
  149. * @param string $group 字段
  150. * @return string
  151. */
  152. protected function checkGroup($group='') {
  153. if(!empty($group)) {
  154. $groups = explode(',',$group);
  155. $_group = array();
  156. foreach ($groups as $field){
  157. // 解析成视图字段
  158. foreach ($this->viewFields as $name=>$val){
  159. $k = isset($val['_as'])?$val['_as']:$name;
  160. $val = $this->_checkFields($name,$val);
  161. if(false !== $_field = array_search($field,$val,true)) {
  162. // 存在视图字段
  163. $field = is_numeric($_field)?$k.'.'.$field:$k.'.'.$_field;
  164. break;
  165. }
  166. }
  167. $_group[] = $field;
  168. }
  169. $group = implode(',',$_group);
  170. }
  171. return $group;
  172. }
  173. /**
  174. * 检查fields表达式中的视图字段
  175. * @access protected
  176. * @param string $fields 字段
  177. * @return string
  178. */
  179. protected function checkFields($fields='') {
  180. if(empty($fields) || '*'==$fields ) {
  181. // 获取全部视图字段
  182. $fields = array();
  183. foreach ($this->viewFields as $name=>$val){
  184. $k = isset($val['_as'])?$val['_as']:$name;
  185. $val = $this->_checkFields($name,$val);
  186. foreach ($val as $key=>$field){
  187. if(is_numeric($key)) {
  188. $fields[] = $k.'.'.$field.' AS '.$field;
  189. }elseif('_' != substr($key,0,1)) {
  190. // 以_开头的为特殊定义
  191. if( false !== strpos($key,'*') || false !== strpos($key,'(') || false !== strpos($key,'.')) {
  192. //如果包含* 或者 使用了sql方法 则不再添加前面的表名
  193. $fields[] = $key.' AS '.$field;
  194. }else{
  195. $fields[] = $k.'.'.$key.' AS '.$field;
  196. }
  197. }
  198. }
  199. }
  200. $fields = implode(',',$fields);
  201. }else{
  202. if(!is_array($fields))
  203. $fields = explode(',',$fields);
  204. // 解析成视图字段
  205. $array = array();
  206. foreach ($fields as $key=>$field){
  207. if(strpos($field,'(') || strpos(strtolower($field),' as ')){
  208. // 使用了函数或者别名
  209. $array[] = $field;
  210. unset($fields[$key]);
  211. }
  212. }
  213. foreach ($this->viewFields as $name=>$val){
  214. $k = isset($val['_as'])?$val['_as']:$name;
  215. $val = $this->_checkFields($name,$val);
  216. foreach ($fields as $key=>$field){
  217. if(false !== $_field = array_search($field,$val,true)) {
  218. // 存在视图字段
  219. if(is_numeric($_field)) {
  220. $array[] = $k.'.'.$field.' AS '.$field;
  221. }elseif('_' != substr($_field,0,1)){
  222. if( false !== strpos($_field,'*') || false !== strpos($_field,'(') || false !== strpos($_field,'.'))
  223. //如果包含* 或者 使用了sql方法 则不再添加前面的表名
  224. $array[] = $_field.' AS '.$field;
  225. else
  226. $array[] = $k.'.'.$_field.' AS '.$field;
  227. }
  228. }
  229. }
  230. }
  231. $fields = implode(',',$array);
  232. }
  233. return $fields;
  234. }
  235. }