Model.class.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  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. // $Id: Model.class.php 2779 2012-02-24 02:56:57Z liu21st $
  12. /**
  13. * ThinkPHP CLI模式Model模型类
  14. * @category Think
  15. * @package Think
  16. * @subpackage Core
  17. * @author liu21st <liu21st@gmail.com>
  18. */
  19. class Model {
  20. // 当前数据库操作对象
  21. protected $db = null;
  22. // 主键名称
  23. protected $pk = 'id';
  24. // 数据表前缀
  25. protected $tablePrefix = '';
  26. // 模型名称
  27. protected $name = '';
  28. // 数据库名称
  29. protected $dbName = '';
  30. // 数据表名(不包含表前缀)
  31. protected $tableName = '';
  32. // 实际数据表名(包含表前缀)
  33. protected $trueTableName ='';
  34. // 最近错误信息
  35. protected $error = '';
  36. // 字段信息
  37. protected $fields = array();
  38. // 数据信息
  39. protected $data = array();
  40. // 查询表达式参数
  41. protected $options = array();
  42. protected $_validate = array(); // 自动验证定义
  43. protected $_auto = array(); // 自动完成定义
  44. // 是否自动检测数据表字段信息
  45. protected $autoCheckFields = true;
  46. // 是否批处理验证
  47. protected $patchValidate = false;
  48. /**
  49. * 架构函数
  50. * 取得DB类的实例对象 字段检查
  51. * @param string $name 模型名称
  52. * @param string $tablePrefix 表前缀
  53. * @param mixed $connection 数据库连接信息
  54. * @access public
  55. */
  56. public function __construct($name='',$tablePrefix='',$connection='') {
  57. // 模型初始化
  58. $this->_initialize();
  59. // 获取模型名称
  60. if(!empty($name)) {
  61. if(strpos($name,'.')) { // 支持 数据库名.模型名的 定义
  62. list($this->dbName,$this->name) = explode('.',$name);
  63. }else{
  64. $this->name = $name;
  65. }
  66. }elseif(empty($this->name)){
  67. $this->name = $this->getModelName();
  68. }
  69. if(!empty($tablePrefix)) {
  70. $this->tablePrefix = $tablePrefix;
  71. }
  72. // 设置表前缀
  73. $this->tablePrefix = $this->tablePrefix?$this->tablePrefix:C('DB_PREFIX');
  74. // 数据库初始化操作
  75. // 获取数据库操作对象
  76. // 当前模型有独立的数据库连接信息
  77. $this->db(0,empty($this->connection)?$connection:$this->connection);
  78. // 字段检测
  79. if(!empty($this->name) && $this->autoCheckFields) $this->_checkTableInfo();
  80. }
  81. /**
  82. * 自动检测数据表信息
  83. * @access protected
  84. * @return void
  85. */
  86. protected function _checkTableInfo() {
  87. // 如果不是Model类 自动记录数据表信息
  88. // 只在第一次执行记录
  89. if(empty($this->fields)) {
  90. // 如果数据表字段没有定义则自动获取
  91. if(C('DB_FIELDS_CACHE')) {
  92. $db = $this->dbName?$this->dbName:C('DB_NAME');
  93. $this->fields = F('_fields/'.$db.'.'.$this->name);
  94. if(!$this->fields) $this->flush();
  95. }else{
  96. // 每次都会读取数据表信息
  97. $this->flush();
  98. }
  99. }
  100. }
  101. /**
  102. * 获取字段信息并缓存
  103. * @access public
  104. * @return void
  105. */
  106. public function flush() {
  107. // 缓存不存在则查询数据表信息
  108. $fields = $this->db->getFields($this->getTableName());
  109. if(!$fields) { // 无法获取字段信息
  110. return false;
  111. }
  112. $this->fields = array_keys($fields);
  113. $this->fields['_autoinc'] = false;
  114. foreach ($fields as $key=>$val){
  115. // 记录字段类型
  116. $type[$key] = $val['type'];
  117. if($val['primary']) {
  118. $this->fields['_pk'] = $key;
  119. if($val['autoinc']) $this->fields['_autoinc'] = true;
  120. }
  121. }
  122. // 记录字段类型信息
  123. if(C('DB_FIELDTYPE_CHECK')) $this->fields['_type'] = $type;
  124. // 2008-3-7 增加缓存开关控制
  125. if(C('DB_FIELDS_CACHE')){
  126. // 永久缓存数据表信息
  127. $db = $this->dbName?$this->dbName:C('DB_NAME');
  128. F('_fields/'.$db.'.'.$this->name,$this->fields);
  129. }
  130. }
  131. /**
  132. * 设置数据对象的值
  133. * @access public
  134. * @param string $name 名称
  135. * @param mixed $value 值
  136. * @return void
  137. */
  138. public function __set($name,$value) {
  139. // 设置数据对象属性
  140. $this->data[$name] = $value;
  141. }
  142. /**
  143. * 获取数据对象的值
  144. * @access public
  145. * @param string $name 名称
  146. * @return mixed
  147. */
  148. public function __get($name) {
  149. return isset($this->data[$name])?$this->data[$name]:null;
  150. }
  151. /**
  152. * 检测数据对象的值
  153. * @access public
  154. * @param string $name 名称
  155. * @return boolean
  156. */
  157. public function __isset($name) {
  158. return isset($this->data[$name]);
  159. }
  160. /**
  161. * 销毁数据对象的值
  162. * @access public
  163. * @param string $name 名称
  164. * @return void
  165. */
  166. public function __unset($name) {
  167. unset($this->data[$name]);
  168. }
  169. /**
  170. * 利用__call方法实现一些特殊的Model方法
  171. * @access public
  172. * @param string $method 方法名称
  173. * @param array $args 调用参数
  174. * @return mixed
  175. */
  176. public function __call($method,$args) {
  177. if(in_array(strtolower($method),array('table','where','order','limit','page','alias','having','group','lock','distinct'),true)) {
  178. // 连贯操作的实现
  179. $this->options[strtolower($method)] = $args[0];
  180. return $this;
  181. }elseif(in_array(strtolower($method),array('count','sum','min','max','avg'),true)){
  182. // 统计查询的实现
  183. $field = isset($args[0])?$args[0]:'*';
  184. return $this->getField(strtoupper($method).'('.$field.') AS tp_'.$method);
  185. }elseif(strtolower(substr($method,0,5))=='getby') {
  186. // 根据某个字段获取记录
  187. $field = parse_name(substr($method,5));
  188. $where[$field] = $args[0];
  189. return $this->where($where)->find();
  190. }else{
  191. throw_exception(__CLASS__.':'.$method.L('_METHOD_NOT_EXIST_'));
  192. return;
  193. }
  194. }
  195. // 回调方法 初始化模型
  196. protected function _initialize() {}
  197. /**
  198. * 对保存到数据库的数据进行处理
  199. * @access protected
  200. * @param mixed $data 要操作的数据
  201. * @return boolean
  202. */
  203. protected function _facade($data) {
  204. // 检查非数据字段
  205. if(!empty($this->fields)) {
  206. foreach ($data as $key=>$val){
  207. if(!in_array($key,$this->fields,true)){
  208. unset($data[$key]);
  209. }elseif(C('DB_FIELDTYPE_CHECK') && is_scalar($val)) {
  210. // 字段类型检查
  211. $this->_parseType($data,$key);
  212. }
  213. }
  214. }
  215. return $data;
  216. }
  217. /**
  218. * 新增数据
  219. * @access public
  220. * @param mixed $data 数据
  221. * @param array $options 表达式
  222. * @return mixed
  223. */
  224. public function add($data='',$options=array()) {
  225. if(empty($data)) {
  226. // 没有传递数据,获取当前数据对象的值
  227. if(!empty($this->data)) {
  228. $data = $this->data;
  229. }else{
  230. $this->error = L('_DATA_TYPE_INVALID_');
  231. return false;
  232. }
  233. }
  234. // 分析表达式
  235. $options = $this->_parseOptions($options);
  236. // 数据处理
  237. $data = $this->_facade($data);
  238. // 写入数据到数据库
  239. $result = $this->db->insert($data,$options);
  240. if(false !== $result ) {
  241. $insertId = $this->getLastInsID();
  242. if($insertId) {
  243. // 自增主键返回插入ID
  244. return $insertId;
  245. }
  246. }
  247. return $result;
  248. }
  249. /**
  250. * 保存数据
  251. * @access public
  252. * @param mixed $data 数据
  253. * @param array $options 表达式
  254. * @return boolean
  255. */
  256. public function save($data='',$options=array()) {
  257. if(empty($data)) {
  258. // 没有传递数据,获取当前数据对象的值
  259. if(!empty($this->data)) {
  260. $data = $this->data;
  261. }else{
  262. $this->error = L('_DATA_TYPE_INVALID_');
  263. return false;
  264. }
  265. }
  266. // 数据处理
  267. $data = $this->_facade($data);
  268. // 分析表达式
  269. $options = $this->_parseOptions($options);
  270. if(!isset($options['where']) ) {
  271. // 如果存在主键数据 则自动作为更新条件
  272. if(isset($data[$this->getPk()])) {
  273. $pk = $this->getPk();
  274. $where[$pk] = $data[$pk];
  275. $options['where'] = $where;
  276. unset($data[$pk]);
  277. }else{
  278. // 如果没有任何更新条件则不执行
  279. $this->error = L('_OPERATION_WRONG_');
  280. return false;
  281. }
  282. }
  283. $result = $this->db->update($data,$options);
  284. return $result;
  285. }
  286. /**
  287. * 删除数据
  288. * @access public
  289. * @param mixed $options 表达式
  290. * @return mixed
  291. */
  292. public function delete($options=array()) {
  293. if(empty($options) && empty($this->options['where'])) {
  294. // 如果删除条件为空 则删除当前数据对象所对应的记录
  295. if(!empty($this->data) && isset($this->data[$this->getPk()]))
  296. return $this->delete($this->data[$this->getPk()]);
  297. else
  298. return false;
  299. }
  300. if(is_numeric($options) || is_string($options)) {
  301. // 根据主键删除记录
  302. $pk = $this->getPk();
  303. if(strpos($options,',')) {
  304. $where[$pk] = array('IN', $options);
  305. }else{
  306. $where[$pk] = $options;
  307. $pkValue = $options;
  308. }
  309. $options = array();
  310. $options['where'] = $where;
  311. }
  312. // 分析表达式
  313. $options = $this->_parseOptions($options);
  314. $result= $this->db->delete($options);
  315. // 返回删除记录个数
  316. return $result;
  317. }
  318. /**
  319. * 查询数据集
  320. * @access public
  321. * @param array $options 表达式参数
  322. * @return mixed
  323. */
  324. public function select($options=array()) {
  325. if(is_string($options) || is_numeric($options)) {
  326. // 根据主键查询
  327. $pk = $this->getPk();
  328. if(strpos($options,',')) {
  329. $where[$pk] = array('IN',$options);
  330. }else{
  331. $where[$pk] = $options;
  332. }
  333. $options = array();
  334. $options['where'] = $where;
  335. }
  336. // 分析表达式
  337. $options = $this->_parseOptions($options);
  338. $resultSet = $this->db->select($options);
  339. if(false === $resultSet) {
  340. return false;
  341. }
  342. if(empty($resultSet)) { // 查询结果为空
  343. return null;
  344. }
  345. return $resultSet;
  346. }
  347. /**
  348. * 分析表达式
  349. * @access proteced
  350. * @param array $options 表达式参数
  351. * @return array
  352. */
  353. protected function _parseOptions($options=array()) {
  354. if(is_array($options))
  355. $options = array_merge($this->options,$options);
  356. // 查询过后清空sql表达式组装 避免影响下次查询
  357. $this->options = array();
  358. if(!isset($options['table']))
  359. // 自动获取表名
  360. $options['table'] =$this->getTableName();
  361. if(!empty($options['alias'])) {
  362. $options['table'] .= ' '.$options['alias'];
  363. }
  364. // 字段类型验证
  365. if(C('DB_FIELDTYPE_CHECK')) {
  366. if(isset($options['where']) && is_array($options['where'])) {
  367. // 对数组查询条件进行字段类型检查
  368. foreach ($options['where'] as $key=>$val){
  369. if(in_array($key,$this->fields,true) && is_scalar($val)){
  370. $this->_parseType($options['where'],$key);
  371. }
  372. }
  373. }
  374. }
  375. return $options;
  376. }
  377. /**
  378. * 数据类型检测
  379. * @access protected
  380. * @param mixed $data 数据
  381. * @param string $key 字段名
  382. * @return void
  383. */
  384. protected function _parseType(&$data,$key) {
  385. $fieldType = strtolower($this->fields['_type'][$key]);
  386. if(false !== strpos($fieldType,'int')) {
  387. $data[$key] = intval($data[$key]);
  388. }elseif(false !== strpos($fieldType,'float') || false !== strpos($fieldType,'double')){
  389. $data[$key] = floatval($data[$key]);
  390. }elseif(false !== strpos($fieldType,'bool')){
  391. $data[$key] = (bool)$data[$key];
  392. }
  393. }
  394. /**
  395. * 查询数据
  396. * @access public
  397. * @param mixed $options 表达式参数
  398. * @return mixed
  399. */
  400. public function find($options=array()) {
  401. if(is_numeric($options) || is_string($options)) {
  402. $where[$this->getPk()] =$options;
  403. $options = array();
  404. $options['where'] = $where;
  405. }
  406. // 总是查找一条记录
  407. $options['limit'] = 1;
  408. // 分析表达式
  409. $options = $this->_parseOptions($options);
  410. $resultSet = $this->db->select($options);
  411. if(false === $resultSet) {
  412. return false;
  413. }
  414. if(empty($resultSet)) {// 查询结果为空
  415. return null;
  416. }
  417. $this->data = $resultSet[0];
  418. return $this->data;
  419. }
  420. /**
  421. * 设置记录的某个字段值
  422. * 支持使用数据库字段和方法
  423. * @access public
  424. * @param string|array $field 字段名
  425. * @param string|array $value 字段值
  426. * @return boolean
  427. */
  428. public function setField($field,$value) {
  429. if(is_array($field)) {
  430. $data = $field;
  431. }else{
  432. $data[$field] = $value;
  433. }
  434. return $this->save($data);
  435. }
  436. /**
  437. * 字段值增长
  438. * @access public
  439. * @param string $field 字段名
  440. * @param integer $step 增长值
  441. * @return boolean
  442. */
  443. public function setInc($field,$step=1) {
  444. return $this->setField($field,array('exp',$field.'+'.$step));
  445. }
  446. /**
  447. * 字段值减少
  448. * @access public
  449. * @param string $field 字段名
  450. * @param integer $step 减少值
  451. * @return boolean
  452. */
  453. public function setDec($field,$step=1) {
  454. return $this->setField($field,array('exp',$field.'-'.$step));
  455. }
  456. /**
  457. * 获取一条记录的某个字段值
  458. * @access public
  459. * @param string $field 字段名
  460. * @param string $spea 字段数据间隔符号
  461. * @return mixed
  462. */
  463. public function getField($field,$sepa=null) {
  464. $options['field'] = $field;
  465. $options = $this->_parseOptions($options);
  466. if(strpos($field,',')) { // 多字段
  467. $resultSet = $this->db->select($options);
  468. if(!empty($resultSet)) {
  469. $_field = explode(',', $field);
  470. $field = array_keys($resultSet[0]);
  471. $move = $_field[0]==$_field[1]?false:true;
  472. $key = array_shift($field);
  473. $key2 = array_shift($field);
  474. $cols = array();
  475. $count = count($_field);
  476. foreach ($resultSet as $result){
  477. $name = $result[$key];
  478. if($move) { // 删除键值记录
  479. unset($result[$key]);
  480. }
  481. if(2==$count) {
  482. $cols[$name] = $result[$key2];
  483. }else{
  484. $cols[$name] = is_null($sepa)?$result:implode($sepa,$result);
  485. }
  486. }
  487. return $cols;
  488. }
  489. }else{ // 查找一条记录
  490. $options['limit'] = 1;
  491. $result = $this->db->select($options);
  492. if(!empty($result)) {
  493. return reset($result[0]);
  494. }
  495. }
  496. return null;
  497. }
  498. /**
  499. * 创建数据对象 但不保存到数据库
  500. * @access public
  501. * @param mixed $data 创建数据
  502. * @return mixed
  503. */
  504. public function create($data='') {
  505. // 如果没有传值默认取POST数据
  506. if(empty($data)) {
  507. $data = $_POST;
  508. }elseif(is_object($data)){
  509. $data = get_object_vars($data);
  510. }
  511. // 验证数据
  512. if(empty($data) || !is_array($data)) {
  513. $this->error = L('_DATA_TYPE_INVALID_');
  514. return false;
  515. }
  516. // 验证完成生成数据对象
  517. if($this->autoCheckFields) { // 开启字段检测 则过滤非法字段数据
  518. $vo = array();
  519. foreach ($this->fields as $key=>$name){
  520. if(substr($key,0,1)=='_') continue;
  521. $val = isset($data[$name])?$data[$name]:null;
  522. //保证赋值有效
  523. if(!is_null($val)){
  524. $vo[$name] = (MAGIC_QUOTES_GPC && is_string($val))? stripslashes($val) : $val;
  525. }
  526. }
  527. }else{
  528. $vo = $data;
  529. }
  530. // 赋值当前数据对象
  531. $this->data = $vo;
  532. // 返回创建的数据以供其他调用
  533. return $vo;
  534. }
  535. /**
  536. * SQL查询
  537. * @access public
  538. * @param mixed $sql SQL指令
  539. * @return mixed
  540. */
  541. public function query($sql) {
  542. if(!empty($sql)) {
  543. if(strpos($sql,'__TABLE__'))
  544. $sql = str_replace('__TABLE__',$this->getTableName(),$sql);
  545. return $this->db->query($sql);
  546. }else{
  547. return false;
  548. }
  549. }
  550. /**
  551. * 执行SQL语句
  552. * @access public
  553. * @param string $sql SQL指令
  554. * @return false | integer
  555. */
  556. public function execute($sql) {
  557. if(!empty($sql)) {
  558. if(strpos($sql,'__TABLE__'))
  559. $sql = str_replace('__TABLE__',$this->getTableName(),$sql);
  560. return $this->db->execute($sql);
  561. }else {
  562. return false;
  563. }
  564. }
  565. /**
  566. * 切换当前的数据库连接
  567. * @access public
  568. * @param integer $linkNum 连接序号
  569. * @param mixed $config 数据库连接信息
  570. * @param array $params 模型参数
  571. * @return Model
  572. */
  573. public function db($linkNum,$config='',$params=array()){
  574. static $_db = array();
  575. if(!isset($_db[$linkNum])) {
  576. // 创建一个新的实例
  577. if(!empty($config) && false === strpos($config,'/')) { // 支持读取配置参数
  578. $config = C($config);
  579. }
  580. $_db[$linkNum] = Db::getInstance($config);
  581. }elseif(NULL === $config){
  582. $_db[$linkNum]->close(); // 关闭数据库连接
  583. unset($_db[$linkNum]);
  584. return ;
  585. }
  586. if(!empty($params)) {
  587. if(is_string($params)) parse_str($params,$params);
  588. foreach ($params as $name=>$value){
  589. $this->setProperty($name,$value);
  590. }
  591. }
  592. // 切换数据库连接
  593. $this->db = $_db[$linkNum];
  594. return $this;
  595. }
  596. /**
  597. * 得到当前的数据对象名称
  598. * @access public
  599. * @return string
  600. */
  601. public function getModelName() {
  602. if(empty($this->name))
  603. $this->name = substr(get_class($this),0,-5);
  604. return $this->name;
  605. }
  606. /**
  607. * 得到完整的数据表名
  608. * @access public
  609. * @return string
  610. */
  611. public function getTableName() {
  612. if(empty($this->trueTableName)) {
  613. $tableName = !empty($this->tablePrefix) ? $this->tablePrefix : '';
  614. if(!empty($this->tableName)) {
  615. $tableName .= $this->tableName;
  616. }else{
  617. $tableName .= parse_name($this->name);
  618. }
  619. $this->trueTableName = strtolower($tableName);
  620. }
  621. return (!empty($this->dbName)?$this->dbName.'.':'').$this->trueTableName;
  622. }
  623. /**
  624. * 启动事务
  625. * @access public
  626. * @return void
  627. */
  628. public function startTrans() {
  629. $this->commit();
  630. $this->db->startTrans();
  631. return ;
  632. }
  633. /**
  634. * 提交事务
  635. * @access public
  636. * @return boolean
  637. */
  638. public function commit() {
  639. return $this->db->commit();
  640. }
  641. /**
  642. * 事务回滚
  643. * @access public
  644. * @return boolean
  645. */
  646. public function rollback() {
  647. return $this->db->rollback();
  648. }
  649. /**
  650. * 返回模型的错误信息
  651. * @access public
  652. * @return string
  653. */
  654. public function getError(){
  655. return $this->error;
  656. }
  657. /**
  658. * 返回数据库的错误信息
  659. * @access public
  660. * @return string
  661. */
  662. public function getDbError() {
  663. return $this->db->getError();
  664. }
  665. /**
  666. * 返回最后插入的ID
  667. * @access public
  668. * @return string
  669. */
  670. public function getLastInsID() {
  671. return $this->db->getLastInsID();
  672. }
  673. /**
  674. * 返回最后执行的sql语句
  675. * @access public
  676. * @return string
  677. */
  678. public function getLastSql() {
  679. return $this->db->getLastSql();
  680. }
  681. // 鉴于getLastSql比较常用 增加_sql 别名
  682. public function _sql(){
  683. return $this->getLastSql();
  684. }
  685. /**
  686. * 获取主键名称
  687. * @access public
  688. * @return string
  689. */
  690. public function getPk() {
  691. return isset($this->fields['_pk'])?$this->fields['_pk']:$this->pk;
  692. }
  693. /**
  694. * 获取数据表字段信息
  695. * @access public
  696. * @return array
  697. */
  698. public function getDbFields(){
  699. if($this->fields) {
  700. $fields = $this->fields;
  701. unset($fields['_autoinc'],$fields['_pk'],$fields['_type']);
  702. return $fields;
  703. }
  704. return false;
  705. }
  706. /**
  707. * 指定查询字段 支持字段排除
  708. * @access public
  709. * @param mixed $field
  710. * @param boolean $except 是否排除
  711. * @return Model
  712. */
  713. public function field($field,$except=false){
  714. if($except) {// 字段排除
  715. if(is_string($field)) {
  716. $field = explode(',',$field);
  717. }
  718. $fields = $this->getDbFields();
  719. $field = $fields?array_diff($fields,$field):$field;
  720. }
  721. $this->options['field'] = $field;
  722. return $this;
  723. }
  724. /**
  725. * 设置数据对象值
  726. * @access public
  727. * @param mixed $data 数据
  728. * @return Model
  729. */
  730. public function data($data){
  731. if(is_object($data)){
  732. $data = get_object_vars($data);
  733. }elseif(is_string($data)){
  734. parse_str($data,$data);
  735. }elseif(!is_array($data)){
  736. throw_exception(L('_DATA_TYPE_INVALID_'));
  737. }
  738. $this->data = $data;
  739. return $this;
  740. }
  741. /**
  742. * 查询SQL组装 join
  743. * @access public
  744. * @param mixed $join
  745. * @return Model
  746. */
  747. public function join($join) {
  748. if(is_array($join))
  749. $this->options['join'] = $join;
  750. else
  751. $this->options['join'][] = $join;
  752. return $this;
  753. }
  754. /**
  755. * 查询SQL组装 union
  756. * @access public
  757. * @param array $union
  758. * @return Model
  759. */
  760. public function union($union) {
  761. if(empty($union)) return $this;
  762. // 转换union表达式
  763. if($union instanceof Model) {
  764. $options = $union->getProperty('options');
  765. if(!isset($options['table'])){
  766. // 自动获取表名
  767. $options['table'] =$union->getTableName();
  768. }
  769. if(!isset($options['field'])) {
  770. $options['field'] =$this->options['field'];
  771. }
  772. }elseif(is_object($union)) {
  773. $options = get_object_vars($union);
  774. }elseif(!is_array($union)){
  775. throw_exception(L('_DATA_TYPE_INVALID_'));
  776. }
  777. $this->options['union'][] = $options;
  778. return $this;
  779. }
  780. /**
  781. * 设置模型的属性值
  782. * @access public
  783. * @param string $name 名称
  784. * @param mixed $value 值
  785. * @return Model
  786. */
  787. public function setProperty($name,$value) {
  788. if(property_exists($this,$name))
  789. $this->$name = $value;
  790. return $this;
  791. }
  792. /**
  793. * 获取模型的属性值
  794. * @access public
  795. * @param string $name 名称
  796. * @return mixed
  797. */
  798. public function getProperty($name){
  799. if(property_exists($this,$name))
  800. return $this->$name;
  801. else
  802. return NULL;
  803. }
  804. }