-
Notifications
You must be signed in to change notification settings - Fork 0
/
Model.class.php
492 lines (462 loc) · 14.8 KB
/
Model.class.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
<?php
defined('IN_TEMPLI') or die('非法引用');
/**
* 模型基类
* @author 七觞酒
* @email 739800600@qq.com
* @date 2013-3-20
*/
class Model
{
public $table_name ='';
//数据库连接对象
protected $db;
//缓存类
public $cache = null;
private $_where = '';
private $_field = '';
private $_order = '';
private $_limit = '';
private $_set = array(); //insert update操作数据
private $_page = array(); //分页配置数组
private $_page_html = ''; //分页 html 代码
//sql 语句
private $_last_sql;
/**
* 构造函数
* @param string $table 表名
* @param int|string $dbSign 数据库唯一标识
* @param array $config 数据库配置
*/
function __construct($table='', $dbSign='master', $config = array())
{
$this->db($dbSign, $config);
$table && $this->table_name = $this->db->prefix.$table;
$this->rest_all_var();
}
/**
* 获取当前模型 的配置信息
* 访问数据的的配置信息
* 数据库表前缀 表名等
* @param $name
* @return mixed
*/
public function __get($name)
{
return isset($this->db->$name) ? $this->db->$name : NULL;
}
/**
* 设置数据库连接 切换数据库
* @param int|string $sign 数据库标识
* @param array $config 数据库配置信息
* @return $this
*/
public function db($sign = 'master', $config = array())
{
static $db = array();
require_once('Cache.class.php');
$this->cache = Cache::factory();
if(!isset($db[$sign])){
if(!$config){
$config = Templi::get_config("db.{$sign}");
}
$className = ucfirst($config['dbdrive']);
$dbdriveFile = 'Model/' . $className . '.class.php';
require_once($dbdriveFile);
$db[$sign] = new $className($config);
}
$this->db = isset($db[$sign]) ? $db[$sign] : $db['master'];
return $this;
}
/**
* 设置操作数据表
* 此方法不建议使用 (使用 此方法 会改变 之前模型 的操作表)
* @param string $table
* @return $this
*/
public function table($table)
{
$this->table_name = $this->db->prefix.$table;
return $this;
}
/**
* 学则字段字段
* @param string $field
*
* @return $this
*/
public function field($field)
{
//不选字段默认为 * 防止用户输入*
if (trim($field) == '*') {
return $this;
}
if (is_array($field)) {
$field = implode(',', array_map(array($this, 'add_special_char'), $field));
} else {
$fields = explode(',', $field);
array_walk($fields, array($this, 'add_special_char'));
$fields = implode(',', $fields);
}
$this->_field && $this->_field .= ', ';
$this->_field .= $fields;
return $this;
}
/**
* where 条件
* @param array or string $where
*
* @param string $compare
* @return $this
*/
public function where($where, $compare = '=')
{
$this->sqls($where, 'AND', $compare);
return $this;
}
/**
* where 条件
* @param array or string $where
* @param string $compare
* @return $this
*/
public function where_or($where, $compare = '=')
{
$this->sqls($where, 'OR', $compare = '=');
return $this;
}
/**
* 给 update insert 赋值
* @param array $data
* @throws Abnormal
* @return $this
*/
public function set(array $data)
{
$this->_set = array_merge($this->_set, $data);
return $this;
}
/**
* oder by
* @param string $order
*
* example id desc
* @return $this
*/
public function order($order)
{
if (is_array($order)) {
foreach ($order as $key =>$val){
$this->_order && $this->_order .= ', ';
$this->_order .= $this->add_special_char($key).' '.$val;
}
} else {
$this->_order && $this->_order .= ', ';
$this->_order .= $order;
}
return $this;
}
/**
* limit
* @param $listNum
* @param null $offset
* @return $this
* @internal param string $limit example 0,20* example 0,20
*/
public function limit($listNum, $offset = NULL)
{
if($offset != NULL){
$this->_limit = " $offset,$listNum";
}else{
$this->_limit = $listNum;
}
return $this;
}
/**
* 分页设置
* @param array $page
* $page['total'] 总数
* $page['listNum'] 每页显示条数
* $page['current_page'] 当前页
* $page['pageNum'] 每页显示的 页码数
* $page['urlrule'] 分页 url 规则
* $page['maxpage'] 最大页数
* @return $this
*/
public function page($page)
{
if (is_array($page)) {
foreach ($this->_page as $key =>$val) {
if ($page[$key] !== NULL) {
$this->_page[$key] = $page[$key];
}
}
} else {
$this->_page['current_page'] = $page;
}
return $this;
}
/**
* 多条查询并分页
* @param null $where
* @param string $field 字段
* @param null $order
* @param int $current_page 当前页
* @param int $listNum 每页显示条数
* @param int $pageNum 每页显示的 页码数
* @param string $urlrule url 规则
* @param $maxpage 最多显示页数
* @internal param \or $string array $where 条件语句 可以为数组
* @internal param string $oreder 排序
* @internal param string $limit 条数限制
* @internal param array $arr [list] 数据列表 $arr['page_html'] 页码html
*
* @return array
*/
public function getlist($where=NULL, $field=NULL, $order=NULL, $current_page=NULL, $listNum=NULL, $pageNum=NULL, $urlrule=NULL, $maxpage=NULL)
{
$arr = array();
$field && $this->field($field);
$where && $this->where($where);
$order && $this->order($order);
//分页
$current_page && $this->page(array(
'total' => $this->count($this->_where),
'current_page' => $current_page,
'listNum' => $listNum,
'pageNum' => $pageNum,
'urlrule' => $urlrule,
'maxpage' => $maxpage
));
require_once('Page.class.php');
$page = new Page($this->_page);
if ($this->_page['listNum']) {
$this->limit($this->_page['listNum'], $page->offset);
}
$arr['list'] = $this->select();
$arr['page_html'] = $page->page_html();
$arr['total'] = $this->_page['total'];
return $arr;
}
/**
* 多条查询
* @param null $where
* @param string $field 字段
* @param null $order
* @param string $limit 条数限制
*
* @internal param \or $string array $where 条件语句 可以为数组
* @internal param string $oreder 排序
*
* @return
*/
public function select($where=NULL, $field=NULL, $order=NULL, $limit=NULL)
{
$where && $this->where($where);
$field && $this->field($field);
$order && $this->order($order);
$limit && $this->limit($limit);
$sql = 'SELECT '.$this->_field.' FROM `'.$this->table_name.'`';
$sql .= $this->_where?' WHERE '.$this->_where:'';
$sql .= $this->_order?' ORDER BY '.$this->_order:'';
$sql .= $limit?' LIMIT '.$limit:'';
return $this->query($sql);
}
/**
* 单条查询
* @param null $where
* @param null $field
* @param null $order
* @internal param \or $string array $where语句 可以是数组
* @internal param string $fields 要查找的字段
* @internal param string $oeder 排序
*
* @return array()
*/
public function find($where=NULL, $field=NULL, $order=NULL)
{
$list = $this->select($where, $field, $order, $limit=1);
return isset($list[0])?$list[0]:array();
}
/**
* 查询数据条数
* @param array or string 查询条件 可以是 数组
*/
public function count($where = NULL)
{
$where && $this->where($where);
$sql = 'SELECT COUNT(*) AS `num` FROM '.$this->table_name;
$sql .=$where?' where '.$this->_where:'';
$sql .=' limit 1';
$res = $this->query($sql);
return isset($res[0]['num'])?$res[0]['num']:$res;
}
/**
* 修改数据
* @param array or string $data要修改的数据 字符串为 sql 语句 数组key 为字段名 value 为字段值
* @param array or string $where 条件语句 可为数组
*
* @return bool
*/
public function update($data = NULL, $where=NULL)
{
$data && $this->set($data);
$where && $this->where($where);
if(!$this->_where)
return false;
foreach($this->_set as $k => $v){
switch(substr($v, 0, 2)){
case '+=':
$v= substr($v,2);
if(is_numeric($v)){
$fields[] =$this->add_special_char($k).'='.$this->add_special_char($k).'+'.$this->escape_string($v, false);
}else{
continue;
}
break;
case '-=':
$v= substr($v,2);
if(is_numeric($v)){
$fields[] =$this->add_special_char($k).'='.$this->add_special_char($k).'-'.$this->escape_string($v, false);
}else{
continue;
}
break;
default:
$fields[]=$this->add_special_char($k).'='.$this->escape_string($v );
break;
}
}
$field = implode(',', $fields);
$sql ='UPDATE `'.$this->table_name.'` SET '.$field.' WHERE '.$this->_where;
return $this->query($sql);
}
/**
* 插入数据
* @param array $data 要添加的数据 key 为字段名 value 为字段值
* @param bool $return_insert_id 是否返回主键 号
* @param bool $replace 是否 为替换插入
* @return bool
*/
public function insert($data = NULL, $return_insert_id = false, $replace = false)
{
$data && $this->set($data);
if(!is_array($this->_set) || count($this->_set) == 0){
return false;
}
$fields = array_keys($this->_set);
$values = array_values($this->_set);
$fields = implode(',',array_map(array($this, 'add_special_char'), $fields));
$values = implode(',',array_map(array($this, 'escape_string'), $values));
$sql = $replace?'REPLACE INTO ':'INSERT INTO ';
$sql .= $this->table_name. '('.$fields.') VALUES ('.$values.')';
$result = $this->query($sql);
return $return_insert_id?$this->db->insert_id():$result;
}
/**
* 删除数据
* @param string or array $where 条件
* @return bool
*/
public function delete($where=NULL)
{
$where && $this->where($where);
if(!$this->_where)
return false;
$sql = 'DELETE FROM ' .$this->table_name. ' WHERE '.$this->_where;
return $this->query($sql);
}
/**
* 执行基本的 mysql查询
*/
public function query($sql)
{
$this->_last_sql = trim($sql);
$this->rest_all_var();
if (strtoupper(substr($this->_last_sql, 0, 6)) == 'SELECT') {
return $this->db->query($this->_last_sql);
} else {
return $this->db->execute($this->_last_sql);
}
}
/**
* 对字段两边加反引号,以保证数据库安全
* @param $value 数组值
* @return string
*/
public function add_special_char(&$value)
{
if('*' == $value || false !== strpos($value, '(') || false !== strpos($value, '.') || false !== strpos ( $value, '`')) {
//不处理包含* 或者 使用了sql方法。
} else {
$value = '`'.trim($value).'`';
}
return $value;
}
/**
* 对字段值两边加引号,以保证数据库安全
* @param $value 数组值
* @param $quotation
* @return string
*/
public function escape_string(&$value, $quotation = 1)
{
if ($quotation) {
$q = '\'';
} else {
$q = '';
}
$value = $q.addslashes($value).$q;
return $value;
}
/**
* 获取最后一次执行的sql 语句
*/
public function last_sql(){
return $this->_last_sql;
}
/**
* 将数组转换为SQL语句
* @param array $where 要生成的数组
* @param string $font 连接串
* @param string $compare 比较字符 (=,!=,in not in, like)
* @throws Abnormal
*/
final public function sqls($where, $font = ' AND ', $compare = '=')
{
if (is_array($where)) {
$compare = strtoupper(trim($compare));
$allowed = array('=', '>=', '<=', '>', '<', '<>', '!=', 'LIKE');
if (!in_array($compare ,$allowed)) {
throw new Abnormal('不支持的比较操作符'.$compare, 500);
}
foreach ($where as $key=>$val) {
$this->_where && $this->_where .= ' '.$font ;
$this->_where .= ' '.$this->add_special_char($key). $compare .$this->escape_string($val, true);
}
} else {
$this->_where && $this->_where .= ' '.$font;
$this->_where .= ' '.$where;
}
}
/**
* 重置 类属性
*/
private function rest_all_var()
{
$this->_where = '';
$this->_field = '*';
$this->_order = '';
$this->_limit = '';
$this->_set = array();
$this->_page = array(
'total'=>0,
'current_page'=>1,
'pageNum'=>8,
'listNum'=>20,
'urlrule'=>'',
'maxpage'=>0
);
$this->_page_html = '';
}
}