Completed
Push — 6.0 ( dd75e4...1011cd )
by liu
03:11
created

Query::__debugInfo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 0
dl 0
loc 8
ccs 0
cts 6
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
// +----------------------------------------------------------------------
1 ignored issue
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: liu21st <[email protected]>
10
// +----------------------------------------------------------------------
11
declare (strict_types = 1);
12
13
namespace think\db;
14
15
use Closure;
16
use PDO;
17
use PDOStatement;
18
use think\App;
19
use think\Collection;
20
use think\Db;
21
use think\db\exception\BindParamException;
22
use think\db\exception\DataNotFoundException;
23
use think\db\exception\ModelNotFoundException;
24
use think\Exception;
25
use think\exception\DbException;
26
use think\exception\PDOException;
27
use think\Model;
28
use think\model\Collection as ModelCollection;
29
use think\model\Relation;
30
use think\model\relation\OneToOne;
31
use think\Paginator;
32
33
/**
34
 * 数据查询类
35
 */
5 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @author tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
36
class Query
37
{
38
    /**
39
     * 当前数据库连接对象
40
     * @var Connection
41
     */
42
    protected $connection;
43
44
    /**
45
     * 当前模型对象
46
     * @var Model
47
     */
48
    protected $model;
49
50
    /**
51
     * Db对象
52
     * @var Db
53
     */
54
    protected $db;
55
56
    /**
57
     * 当前数据表名称(不含前缀)
58
     * @var string
59
     */
60
    protected $name = '';
61
62
    /**
63
     * 当前数据表主键
64
     * @var string|array
65
     */
66
    protected $pk;
67
68
    /**
69
     * 当前数据表前缀
70
     * @var string
71
     */
72
    protected $prefix = '';
73
74
    /**
75
     * 当前查询参数
76
     * @var array
77
     */
78
    protected $options = [];
79
80
    /**
81
     * 当前参数绑定
82
     * @var array
83
     */
84
    protected $bind = [];
85
86
    /**
87
     * 日期查询表达式
88
     * @var array
89
     */
90
    protected $timeRule = [
91
        'today'      => ['today', 'tomorrow'],
92
        'yesterday'  => ['yesterday', 'today'],
93
        'week'       => ['this week 00:00:00', 'next week 00:00:00'],
94
        'last week'  => ['last week 00:00:00', 'this week 00:00:00'],
95
        'month'      => ['first Day of this month 00:00:00', 'first Day of next month 00:00:00'],
96
        'last month' => ['first Day of last month 00:00:00', 'first Day of this month 00:00:00'],
97
        'year'       => ['this year 1/1', 'next year 1/1'],
98
        'last year'  => ['last year 1/1', 'this year 1/1'],
99
    ];
100
101
    /**
102
     * 架构函数
103
     * @access public
104
     * @param Connection $connection 数据库连接对象
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
105
     */
106
    public function __construct(Connection $connection)
107
    {
108
        $this->connection = $connection;
109
110
        $this->prefix = $this->connection->getConfig('prefix');
111
    }
112
113
    /**
114
     * 创建一个新的查询对象
115
     * @access public
116
     * @return Query
117
     */
118
    public function newQuery()
119
    {
120
        $query = new static($this->connection);
121
122
        if ($this->model) {
123
            $query->model($this->model);
124
        }
125
126
        if (isset($this->options['table'])) {
127
            $query->table($this->options['table']);
128
        } else {
129
            $query->name($this->name);
130
        }
131
132
        $query->setDb($this->db);
133
134
        return $query;
135
    }
136
137
    /**
138
     * 利用__call方法实现一些特殊的Model方法
139
     * @access public
140
     * @param string $method 方法名称
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
141
     * @param array  $args   调用参数
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
142
     * @return mixed
143
     * @throws DbException
144
     * @throws Exception
145
     */
146
    public function __call(string $method, array $args)
147
    {
148
        if (strtolower(substr($method, 0, 5)) == 'getby') {
149
            // 根据某个字段获取记录
150
            $field = App::parseName(substr($method, 5));
151
            return $this->where($field, '=', $args[0])->find();
152
        } elseif (strtolower(substr($method, 0, 10)) == 'getfieldby') {
153
            // 根据某个字段获取记录的某个值
154
            $name = App::parseName(substr($method, 10));
155
            return $this->where($name, '=', $args[0])->value($args[1]);
156
        } elseif (strtolower(substr($method, 0, 7)) == 'whereor') {
157
            $name = App::parseName(substr($method, 7));
158
            array_unshift($args, $name);
159
            return call_user_func_array([$this, 'whereOr'], $args);
160
        } elseif (strtolower(substr($method, 0, 5)) == 'where') {
161
            $name = App::parseName(substr($method, 5));
162
            array_unshift($args, $name);
163
            return call_user_func_array([$this, 'where'], $args);
164
        } elseif ($this->model && method_exists($this->model, 'scope' . $method)) {
165
            // 动态调用命名范围
166
            $method = 'scope' . $method;
167
            array_unshift($args, $this);
168
169
            call_user_func_array([$this->model, $method], $args);
170
            return $this;
171
        } else {
172
            throw new Exception('method not exist:' . static::class . '->' . $method);
173
        }
174
    }
175
176
    /**
177
     * 获取当前的数据库Connection对象
178
     * @access public
179
     * @return Connection
180
     */
181
    public function getConnection()
182
    {
183
        return $this->connection;
184
    }
185
186
    /**
187
     * 设置当前的数据库Connection对象
188
     * @access public
189
     * @param Connection $connection 数据库连接对象
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
190
     * @return $this
191
     */
192
    public function setConnection($connection)
193
    {
194
        $this->connection = $connection;
195
196
        return $this;
197
    }
198
199
    /**
200
     * 设置Db对象
201
     * @access public
202
     * @param Db $db
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
203
     * @return $this
204
     */
205
    public function setDb(Db $db)
206
    {
207
        $this->db = $db;
208
        $this->connection->setDb($db);
209
        return $this;
210
    }
211
212
    /**
213
     * 获取Db对象
214
     * @access public
215
     * @return Db
216
     */
217
    public function getDb()
218
    {
219
        return $this->db;
220
    }
221
222
    /**
223
     * 指定模型
224
     * @access public
225
     * @param Model $model 模型对象实例
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
226
     * @return $this
227
     */
228
    public function model(Model $model)
229
    {
230
        $this->model = $model;
231
        return $this;
232
    }
233
234
    /**
235
     * 获取当前的模型对象
236
     * @access public
237
     * @return Model|null
238
     */
239
    public function getModel()
240
    {
241
        return $this->model ? $this->model->setQuery($this) : null;
242
    }
243
244
    /**
245
     * 指定当前数据表名(不含前缀)
246
     * @access public
247
     * @param string $name 不含前缀的数据表名字
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
248
     * @return $this
249
     */
250
    public function name(string $name)
251
    {
252
        $this->name = $name;
253
        return $this;
254
    }
255
256
    /**
257
     * 获取当前的数据表名称
258
     * @access public
259
     * @return string
260
     */
261
    public function getName(): string
262
    {
263
        return $this->name ?: $this->model->getName();
264
    }
265
266
    /**
267
     * 获取数据库的配置参数
268
     * @access public
269
     * @param string $name 参数名称
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
270
     * @return mixed
271
     */
272
    public function getConfig(string $name = '')
273
    {
274
        return $this->connection->getConfig($name);
275
    }
276
277
    /**
278
     * 得到当前或者指定名称的数据表
279
     * @access public
280
     * @param string $name 不含前缀的数据表名字
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
281
     * @return mixed
282
     */
283
    public function getTable(string $name = '')
284
    {
285
        if (empty($name) && isset($this->options['table'])) {
286
            return $this->options['table'];
287
        }
288
289
        $name = $name ?: $this->name;
290
291
        return $this->prefix . App::parseName($name);
292
    }
293
294
    /**
295
     * 获取数据表字段信息
296
     * @access public
297
     * @param string $tableName 数据表名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
298
     * @return array
299
     */
300
    public function getTableFields($tableName = ''): array
301
    {
302
        if ('' == $tableName) {
303
            $tableName = $this->getTable();
304
        }
305
306
        return $this->connection->getTableFields($tableName);
307
    }
308
309
    /**
310
     * 设置字段类型信息
311
     * @access public
312
     * @param array $type 字段类型信息
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
313
     * @return $this
314
     */
315
    public function setFieldType(array $type)
316
    {
317
        $this->options['field_type'] = $type;
318
        return $this;
319
    }
320
321
    /**
322
     * 获取字段类型信息
323
     * @access public
324
     * @return array
325
     */
326
    public function getFieldsType(): array
327
    {
328
        if (!empty($this->options['field_type'])) {
329
            return $this->options['field_type'];
330
        }
331
332
        return $this->connection->getFieldsType($this->getTable());
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->connection...Type($this->getTable()) could return the type string which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
333
    }
334
335
    /**
336
     * 获取字段类型信息
337
     * @access public
338
     * @param string $field 字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
339
     * @return string|null
340
     */
341
    public function getFieldType(string $field)
342
    {
343
        $fieldType = $this->getFieldsType();
344
345
        return $fieldType[$field] ?? null;
346
    }
347
348
    /**
349
     * 获取字段类型信息
350
     * @access public
351
     * @return array
352
     */
353
    public function getFieldsBindType(): array
354
    {
355
        $fieldType = $this->getFieldsType();
356
357
        return array_map([$this->connection, 'getFieldBindType'], $fieldType);
358
    }
359
360
    /**
361
     * 获取字段类型信息
362
     * @access public
363
     * @param string $field 字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
364
     * @return int
365
     */
366
    public function getFieldBindType(string $field): int
367
    {
368
        $fieldType = $this->getFieldType($field);
369
370
        return $this->connection->getFieldBindType($fieldType ?: '');
371
    }
372
373
    /**
374
     * 执行查询 返回数据集
375
     * @access public
376
     * @param string $sql  sql指令
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
377
     * @param array  $bind 参数绑定
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
378
     * @return array
379
     * @throws BindParamException
380
     * @throws PDOException
381
     */
382
    public function query(string $sql, array $bind = []): array
383
    {
384
        return $this->connection->query($this, $sql, $bind, true);
385
    }
386
387
    /**
388
     * 执行语句
389
     * @access public
390
     * @param string $sql  sql指令
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
391
     * @param array  $bind 参数绑定
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
392
     * @return int
393
     * @throws BindParamException
394
     * @throws PDOException
395
     */
396
    public function execute(string $sql, array $bind = []): int
397
    {
398
        return $this->connection->execute($this, $sql, $bind, true);
399
    }
400
401
    /**
402
     * 获取最近插入的ID
403
     * @access public
404
     * @param string $sequence 自增序列名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
405
     * @return string
406
     */
407
    public function getLastInsID(string $sequence = null): string
408
    {
409
        return $this->connection->getLastInsID($sequence);
410
    }
411
412
    /**
413
     * 获取返回或者影响的记录数
414
     * @access public
415
     * @return integer
416
     */
417
    public function getNumRows(): int
418
    {
419
        return $this->connection->getNumRows();
420
    }
421
422
    /**
423
     * 获取最近一次查询的sql语句
424
     * @access public
425
     * @return string
426
     */
427
    public function getLastSql(): string
428
    {
429
        return $this->connection->getLastSql();
430
    }
431
432
    /**
433
     * 执行数据库事务
434
     * @access public
435
     * @param callable $callback 数据操作方法回调
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
436
     * @return mixed
437
     */
438
    public function transaction(callable $callback)
439
    {
440
        return $this->connection->transaction($callback);
441
    }
442
443
    /**
444
     * 启动事务
445
     * @access public
446
     * @return void
447
     */
448
    public function startTrans(): void
449
    {
450
        $this->connection->startTrans();
451
    }
452
453
    /**
454
     * 用于非自动提交状态下面的查询提交
455
     * @access public
456
     * @return void
457
     * @throws PDOException
458
     */
459
    public function commit(): void
460
    {
461
        $this->connection->commit();
462
    }
463
464
    /**
465
     * 事务回滚
466
     * @access public
467
     * @return void
468
     * @throws PDOException
469
     */
470
    public function rollback(): void
471
    {
472
        $this->connection->rollback();
473
    }
474
475
    /**
476
     * 批处理执行SQL语句
477
     * 批处理的指令都认为是execute操作
478
     * @access public
479
     * @param array $sql SQL批处理指令
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
480
     * @return bool
481
     */
482
    public function batchQuery(array $sql = []): bool
483
    {
484
        return $this->connection->batchQuery($this, $sql);
485
    }
486
487
    /**
488
     * 得到某个字段的值
489
     * @access public
490
     * @param string $field   字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
491
     * @param mixed  $default 默认值
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
492
     * @return mixed
493
     */
494
    public function value(string $field, $default = null)
495
    {
496
        return $this->connection->value($this, $field, $default);
497
    }
498
499
    /**
500
     * 得到某个列的数组
501
     * @access public
502
     * @param string $field 字段名 多个字段用逗号分隔
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
503
     * @param string $key   索引
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
504
     * @return array
505
     */
506
    public function column(string $field, string $key = ''): array
507
    {
508
        return $this->connection->column($this, $field, $key);
509
    }
510
511
    /**
512
     * 聚合查询
513
     * @access protected
514
     * @param string     $aggregate 聚合方法
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
515
     * @param string|Raw $field     字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
516
     * @param bool       $force     强制转为数字类型
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
517
     * @return mixed
518
     */
519
    protected function aggregate(string $aggregate, $field, bool $force = false)
520
    {
521
        return $this->connection->aggregate($this, $aggregate, $field, $force);
522
    }
523
524
    /**
525
     * COUNT查询
526
     * @access public
527
     * @param string|Raw $field 字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
528
     * @return int
529
     */
530
    public function count(string $field = '*'): int
531
    {
532
        if (!empty($this->options['group'])) {
533
            // 支持GROUP
534
            $options = $this->getOptions();
535
            $subSql  = $this->options($options)->field('count(' . $field . ') AS think_count')->bind($this->bind)->buildSql();
536
537
            $query = $this->newQuery()->table([$subSql => '_group_count_']);
538
539
            $count = $query->aggregate('COUNT', '*');
540
        } else {
541
            $count = $this->aggregate('COUNT', $field);
542
        }
543
544
        return (int) $count;
545
    }
546
547
    /**
548
     * SUM查询
549
     * @access public
550
     * @param string|Raw $field 字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
551
     * @return float
552
     */
553
    public function sum($field): float
554
    {
555
        return $this->aggregate('SUM', $field, true);
556
    }
557
558
    /**
559
     * MIN查询
560
     * @access public
561
     * @param string|Raw $field 字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
562
     * @param bool       $force 强制转为数字类型
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
563
     * @return mixed
564
     */
565
    public function min($field, bool $force = true)
566
    {
567
        return $this->aggregate('MIN', $field, $force);
568
    }
569
570
    /**
571
     * MAX查询
572
     * @access public
573
     * @param string|Raw $field 字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
574
     * @param bool       $force 强制转为数字类型
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
575
     * @return mixed
576
     */
577
    public function max($field, bool $force = true)
578
    {
579
        return $this->aggregate('MAX', $field, $force);
580
    }
581
582
    /**
583
     * AVG查询
584
     * @access public
585
     * @param string|Raw $field 字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
586
     * @return float
587
     */
588
    public function avg($field): float
589
    {
590
        return $this->aggregate('AVG', $field, true);
591
    }
592
593
    /**
594
     * 查询SQL组装 join
595
     * @access public
596
     * @param mixed  $join      关联的表名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
597
     * @param mixed  $condition 条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
598
     * @param string $type      JOIN类型
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
599
     * @param array  $bind      参数绑定
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
600
     * @return $this
601
     */
602
    public function join($join, string $condition = null, string $type = 'INNER', array $bind = [])
603
    {
604
        $table = $this->getJoinTable($join);
605
606
        if (!empty($bind) && $condition) {
607
            $this->bindParams($condition, $bind);
608
        }
609
610
        $this->options['join'][] = [$table, strtoupper($type), $condition];
611
612
        return $this;
613
    }
614
615
    /**
616
     * LEFT JOIN
617
     * @access public
618
     * @param mixed $join      关联的表名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
619
     * @param mixed $condition 条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
620
     * @param array $bind      参数绑定
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
621
     * @return $this
622
     */
623
    public function leftJoin($join, string $condition = null, array $bind = [])
624
    {
625
        return $this->join($join, $condition, 'LEFT', $bind);
626
    }
627
628
    /**
629
     * RIGHT JOIN
630
     * @access public
631
     * @param mixed $join      关联的表名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
632
     * @param mixed $condition 条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
633
     * @param array $bind      参数绑定
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
634
     * @return $this
635
     */
636
    public function rightJoin($join, string $condition = null, array $bind = [])
637
    {
638
        return $this->join($join, $condition, 'RIGHT', $bind);
639
    }
640
641
    /**
642
     * FULL JOIN
643
     * @access public
644
     * @param mixed $join      关联的表名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
645
     * @param mixed $condition 条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
646
     * @param array $bind      参数绑定
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
647
     * @return $this
648
     */
649
    public function fullJoin($join, string $condition = null, array $bind = [])
650
    {
651
        return $this->join($join, $condition, 'FULL');
652
    }
653
654
    /**
655
     * 获取Join表名及别名 支持
656
     * ['prefix_table或者子查询'=>'alias'] 'table alias'
657
     * @access protected
658
     * @param array|string|Raw $join  JION表名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
659
     * @param string           $alias 别名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
660
     * @return string|array
661
     */
662
    protected function getJoinTable($join, &$alias = null)
663
    {
664
        if (is_array($join)) {
665
            $table = $join;
666
            $alias = array_shift($join);
667
            return $table;
668
        } elseif ($join instanceof Raw) {
669
            return $join;
670
        }
671
672
        $join = trim($join);
673
674
        if (false !== strpos($join, '(')) {
675
            // 使用子查询
676
            $table = $join;
677
        } else {
678
            // 使用别名
679
            if (strpos($join, ' ')) {
680
                // 使用别名
681
                list($table, $alias) = explode(' ', $join);
682
            } else {
683
                $table = $join;
684
                if (false === strpos($join, '.')) {
685
                    $alias = $join;
686
                }
687
            }
688
689
            if ($this->prefix && false === strpos($table, '.') && 0 !== strpos($table, $this->prefix)) {
690
                $table = $this->getTable($table);
691
            }
692
        }
693
694
        if (!empty($alias) && $table != $alias) {
695
            $table = [$table => $alias];
696
        }
697
698
        return $table;
699
    }
700
701
    /**
702
     * 查询SQL组装 union
703
     * @access public
704
     * @param mixed   $union UNION
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
705
     * @param boolean $all   是否适用UNION ALL
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
706
     * @return $this
707
     */
708
    public function union($union, bool $all = false)
709
    {
710
        $this->options['union']['type'] = $all ? 'UNION ALL' : 'UNION';
711
712
        if (is_array($union)) {
713
            $this->options['union'] = array_merge($this->options['union'], $union);
714
        } else {
715
            $this->options['union'][] = $union;
716
        }
717
718
        return $this;
719
    }
720
721
    /**
722
     * 查询SQL组装 union all
723
     * @access public
724
     * @param mixed $union UNION数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
725
     * @return $this
726
     */
727
    public function unionAll($union)
728
    {
729
        return $this->union($union, true);
730
    }
731
732
    /**
733
     * 指定查询字段 支持字段排除和指定数据表
734
     * @access public
735
     * @param mixed   $field     字段信息
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
736
     * @param boolean $except    是否排除
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
737
     * @param string  $tableName 数据表名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
738
     * @param string  $prefix    字段前缀
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
739
     * @param string  $alias     别名前缀
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
740
     * @return $this
741
     */
742
    public function field($field, bool $except = false, string $tableName = '', string $prefix = '', string $alias = '')
743
    {
744
        if (empty($field)) {
745
            return $this;
746
        } elseif ($field instanceof Raw) {
747
            $this->options['field'][] = $field;
748
            return $this;
749
        }
750
751
        if (is_string($field)) {
752
            if (preg_match('/[\<\'\"\(]/', $field)) {
753
                return $this->fieldRaw($field);
754
            }
755
756
            $field = array_map('trim', explode(',', $field));
757
        }
758
759
        if (true === $field) {
760
            // 获取全部字段
761
            $fields = $this->getTableFields($tableName);
762
            $field  = $fields ?: ['*'];
0 ignored issues
show
introduced by
$fields is an empty array, thus is always false.
Loading history...
763
        } elseif ($except) {
764
            // 字段排除
765
            $fields = $this->getTableFields($tableName);
766
            $field  = $fields ? array_diff($fields, $field) : $field;
0 ignored issues
show
introduced by
$fields is an empty array, thus is always false.
Loading history...
767
        }
768
769
        if ($tableName) {
770
            // 添加统一的前缀
771
            $prefix = $prefix ?: $tableName;
772
            foreach ($field as $key => &$val) {
773
                if (is_numeric($key) && $alias) {
774
                    $field[$prefix . '.' . $val] = $alias . $val;
775
                    unset($field[$key]);
776
                } elseif (is_numeric($key)) {
777
                    $val = $prefix . '.' . $val;
778
                }
779
            }
780
        }
781
782
        if (isset($this->options['field'])) {
783
            $field = array_merge((array) $this->options['field'], $field);
784
        }
785
786
        $this->options['field'] = array_unique($field);
787
788
        return $this;
789
    }
790
791
    /**
792
     * 表达式方式指定查询字段
793
     * @access public
794
     * @param string $field 字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
795
     * @return $this
796
     */
797
    public function fieldRaw(string $field)
798
    {
799
        $this->options['field'][] = new Raw($field);
800
801
        return $this;
802
    }
803
804
    /**
805
     * 设置数据
806
     * @access public
807
     * @param array $data 数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
808
     * @return $this
809
     */
810
    public function data(array $data)
811
    {
812
        $this->options['data'] = $data;
813
814
        return $this;
815
    }
816
817
    /**
818
     * 字段值增长
819
     * @access public
820
     * @param string  $field    字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
821
     * @param float   $step     增长值
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
822
     * @param integer $lazyTime 延时时间(s)
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
823
     * @param string  $op       INC/DEC
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
824
     * @return $this
825
     */
826
    public function inc(string $field, float $step = 1, int $lazyTime = 0, string $op = 'INC')
827
    {
828
        if ($lazyTime > 0) {
829
            // 延迟写入
830
            $condition = $this->options['where'] ?? [];
831
832
            $guid = md5($this->getTable() . '_' . $field . '_' . serialize($condition));
833
            $step = $this->connection->lazyWrite($op, $guid, $step, $lazyTime);
834
835
            if (false === $step) {
836
                return $this;
837
            }
838
839
            $op = 'INC';
840
        }
841
842
        $this->options['data'][$field] = [$op, $step];
843
844
        return $this;
845
    }
846
847
    /**
848
     * 字段值减少
849
     * @access public
850
     * @param string  $field    字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
851
     * @param float   $step     增长值
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
852
     * @param integer $lazyTime 延时时间(s)
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
853
     * @return $this
854
     */
855
    public function dec(string $field, float $step = 1, int $lazyTime = 0)
856
    {
857
        return $this->inc($field, $step, $lazyTime, 'DEC');
858
    }
859
860
    /**
861
     * 使用表达式设置数据
862
     * @access public
863
     * @param string $field 字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
864
     * @param string $value 字段值
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
865
     * @return $this
866
     */
867
    public function exp(string $field, string $value)
868
    {
869
        $this->options['data'][$field] = new Raw($value);
870
        return $this;
871
    }
872
873
    /**
874
     * 指定JOIN查询字段
875
     * @access public
876
     * @param string|array $join  数据表
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
877
     * @param string|array $field 查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
878
     * @param string       $on    JOIN条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
879
     * @param string       $type  JOIN类型
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
880
     * @param array        $bind  参数绑定
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
881
     * @return $this
882
     */
883
    public function view($join, $field = true, $on = null, string $type = 'INNER', array $bind = [])
884
    {
885
        $this->options['view'] = true;
886
887
        $fields = [];
888
        $table  = $this->getJoinTable($join, $alias);
889
890
        if (true === $field) {
891
            $fields = $alias . '.*';
892
        } else {
893
            if (is_string($field)) {
894
                $field = explode(',', $field);
895
            }
896
897
            foreach ($field as $key => $val) {
898
                if (is_numeric($key)) {
899
                    $fields[] = $alias . '.' . $val;
900
901
                    $this->options['map'][$val] = $alias . '.' . $val;
902
                } else {
903
                    if (preg_match('/[,=\.\'\"\(\s]/', $key)) {
904
                        $name = $key;
905
                    } else {
906
                        $name = $alias . '.' . $key;
907
                    }
908
909
                    $fields[] = $name . ' AS ' . $val;
910
911
                    $this->options['map'][$val] = $name;
912
                }
913
            }
914
        }
915
916
        $this->field($fields);
917
918
        if ($on) {
919
            $this->join($table, $on, $type, $bind);
920
        } else {
921
            $this->table($table);
922
        }
923
924
        return $this;
925
    }
926
927
    /**
928
     * 指定AND查询条件
929
     * @access public
930
     * @param mixed $field     查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
931
     * @param mixed $op        查询表达式
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
932
     * @param mixed $condition 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
933
     * @return $this
934
     */
935
    public function where($field, $op = null, $condition = null)
936
    {
937
        if ($field instanceof $this) {
938
            $this->options['where'] = $field->getOptions('where');
939
            return $this;
940
        }
941
942
        $param = func_get_args();
943
        array_shift($param);
944
        return $this->parseWhereExp('AND', $field, $op, $condition, $param);
945
    }
946
947
    /**
948
     * 指定OR查询条件
949
     * @access public
950
     * @param mixed $field     查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
951
     * @param mixed $op        查询表达式
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
952
     * @param mixed $condition 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
953
     * @return $this
954
     */
955
    public function whereOr($field, $op = null, $condition = null)
956
    {
957
        $param = func_get_args();
958
        array_shift($param);
959
        return $this->parseWhereExp('OR', $field, $op, $condition, $param);
960
    }
961
962
    /**
963
     * 指定XOR查询条件
964
     * @access public
965
     * @param mixed $field     查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
966
     * @param mixed $op        查询表达式
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
967
     * @param mixed $condition 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
968
     * @return $this
969
     */
970
    public function whereXor($field, $op = null, $condition = null)
971
    {
972
        $param = func_get_args();
973
        array_shift($param);
974
        return $this->parseWhereExp('XOR', $field, $op, $condition, $param);
975
    }
976
977
    /**
978
     * 指定Null查询条件
979
     * @access public
980
     * @param mixed  $field 查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
981
     * @param string $logic 查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
982
     * @return $this
983
     */
984
    public function whereNull(string $field, string $logic = 'AND')
985
    {
986
        return $this->parseWhereExp($logic, $field, 'NULL', null, [], true);
987
    }
988
989
    /**
990
     * 指定NotNull查询条件
991
     * @access public
992
     * @param mixed  $field 查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
993
     * @param string $logic 查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
994
     * @return $this
995
     */
996
    public function whereNotNull(string $field, string $logic = 'AND')
997
    {
998
        return $this->parseWhereExp($logic, $field, 'NOTNULL', null, [], true);
999
    }
1000
1001
    /**
1002
     * 指定Exists查询条件
1003
     * @access public
1004
     * @param mixed  $condition 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1005
     * @param string $logic     查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1006
     * @return $this
1007
     */
1008
    public function whereExists($condition, string $logic = 'AND')
1009
    {
1010
        if (is_string($condition)) {
1011
            $condition = new Raw($condition);
1012
        }
1013
1014
        $this->options['where'][strtoupper($logic)][] = ['', 'EXISTS', $condition];
1015
        return $this;
1016
    }
1017
1018
    /**
1019
     * 指定NotExists查询条件
1020
     * @access public
1021
     * @param mixed  $condition 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1022
     * @param string $logic     查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1023
     * @return $this
1024
     */
1025
    public function whereNotExists($condition, string $logic = 'AND')
1026
    {
1027
        if (is_string($condition)) {
1028
            $condition = new Raw($condition);
1029
        }
1030
1031
        $this->options['where'][strtoupper($logic)][] = ['', 'NOT EXISTS', $condition];
1032
        return $this;
1033
    }
1034
1035
    /**
1036
     * 指定In查询条件
1037
     * @access public
1038
     * @param mixed  $field     查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1039
     * @param mixed  $condition 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1040
     * @param string $logic     查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1041
     * @return $this
1042
     */
1043
    public function whereIn(string $field, $condition, string $logic = 'AND')
1044
    {
1045
        return $this->parseWhereExp($logic, $field, 'IN', $condition, [], true);
1046
    }
1047
1048
    /**
1049
     * 指定NotIn查询条件
1050
     * @access public
1051
     * @param mixed  $field     查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1052
     * @param mixed  $condition 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1053
     * @param string $logic     查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1054
     * @return $this
1055
     */
1056
    public function whereNotIn(string $field, $condition, string $logic = 'AND')
1057
    {
1058
        return $this->parseWhereExp($logic, $field, 'NOT IN', $condition, [], true);
1059
    }
1060
1061
    /**
1062
     * 指定Like查询条件
1063
     * @access public
1064
     * @param mixed  $field     查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1065
     * @param mixed  $condition 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1066
     * @param string $logic     查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1067
     * @return $this
1068
     */
1069
    public function whereLike(string $field, $condition, string $logic = 'AND')
1070
    {
1071
        return $this->parseWhereExp($logic, $field, 'LIKE', $condition, [], true);
1072
    }
1073
1074
    /**
1075
     * 指定NotLike查询条件
1076
     * @access public
1077
     * @param mixed  $field     查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1078
     * @param mixed  $condition 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1079
     * @param string $logic     查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1080
     * @return $this
1081
     */
1082
    public function whereNotLike(string $field, $condition, string $logic = 'AND')
1083
    {
1084
        return $this->parseWhereExp($logic, $field, 'NOT LIKE', $condition, [], true);
1085
    }
1086
1087
    /**
1088
     * 指定Between查询条件
1089
     * @access public
1090
     * @param mixed  $field     查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1091
     * @param mixed  $condition 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1092
     * @param string $logic     查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1093
     * @return $this
1094
     */
1095
    public function whereBetween(string $field, $condition, string $logic = 'AND')
1096
    {
1097
        return $this->parseWhereExp($logic, $field, 'BETWEEN', $condition, [], true);
1098
    }
1099
1100
    /**
1101
     * 指定NotBetween查询条件
1102
     * @access public
1103
     * @param mixed  $field     查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1104
     * @param mixed  $condition 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1105
     * @param string $logic     查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1106
     * @return $this
1107
     */
1108
    public function whereNotBetween(string $field, $condition, string $logic = 'AND')
1109
    {
1110
        return $this->parseWhereExp($logic, $field, 'NOT BETWEEN', $condition, [], true);
1111
    }
1112
1113
    /**
1114
     * 指定FIND_IN_SET查询条件
1115
     * @access public
1116
     * @param mixed  $field     查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1117
     * @param mixed  $condition 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1118
     * @param string $logic     查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1119
     * @return $this
1120
     */
1121
    public function whereFindInSet(string $field, $condition, string $logic = 'AND')
1122
    {
1123
        return $this->parseWhereExp($logic, $field, 'FIND IN SET', $condition, [], true);
1124
    }
1125
1126
    /**
1127
     * 比较两个字段
1128
     * @access public
1129
     * @param string $field1   查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1130
     * @param string $operator 比较操作符
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1131
     * @param string $field2   比较字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1132
     * @param string $logic    查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1133
     * @return $this
1134
     */
1135
    public function whereColumn(string $field1, string $operator, string $field2 = null, string $logic = 'AND')
1136
    {
1137
        if (is_null($field2)) {
1138
            $field2   = $operator;
1139
            $operator = '=';
1140
        }
1141
1142
        return $this->parseWhereExp($logic, $field1, 'COLUMN', [$operator, $field2], [], true);
1143
    }
1144
1145
    /**
1146
     * 设置软删除字段及条件
1147
     * @access public
1148
     * @param string $field     查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1149
     * @param mixed  $condition 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1150
     * @return $this
1151
     */
1152
    public function useSoftDelete(string $field, $condition = null)
1153
    {
1154
        if ($field) {
1155
            $this->options['soft_delete'] = [$field, $condition];
1156
        }
1157
1158
        return $this;
1159
    }
1160
1161
    /**
1162
     * 指定Exp查询条件
1163
     * @access public
1164
     * @param mixed  $field 查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1165
     * @param string $where 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1166
     * @param array  $bind  参数绑定
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1167
     * @param string $logic 查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1168
     * @return $this
1169
     */
1170
    public function whereExp(string $field, string $where, array $bind = [], string $logic = 'AND')
1171
    {
1172
        if (!empty($bind)) {
1173
            $this->bindParams($where, $bind);
1174
        }
1175
1176
        $this->options['where'][$logic][] = [$field, 'EXP', new Raw($where)];
1177
1178
        return $this;
1179
    }
1180
1181
    /**
1182
     * 指定字段Raw查询
1183
     * @access public
1184
     * @param string $field     查询字段表达式
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1185
     * @param mixed  $op        查询表达式
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1186
     * @param string $condition 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1187
     * @param string $logic     查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1188
     * @return $this
1189
     */
1190
    public function whereFieldRaw(string $field, $op, $condition = null, string $logic = 'AND')
1191
    {
1192
        if (is_null($condition)) {
1193
            $condition = $op;
1194
            $op        = '=';
1195
        }
1196
1197
        $this->options['where'][$logic][] = [new Raw($field), $op, $condition];
1198
        return $this;
1199
    }
1200
1201
    /**
1202
     * 指定表达式查询条件
1203
     * @access public
1204
     * @param string $where 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1205
     * @param array  $bind  参数绑定
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1206
     * @param string $logic 查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1207
     * @return $this
1208
     */
1209
    public function whereRaw(string $where, array $bind = [], string $logic = 'AND')
1210
    {
1211
        if (!empty($bind)) {
1212
            $this->bindParams($where, $bind);
1213
        }
1214
1215
        $this->options['where'][$logic][] = new Raw($where);
1216
1217
        return $this;
1218
    }
1219
1220
    /**
1221
     * 指定表达式查询条件 OR
1222
     * @access public
1223
     * @param string $where 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1224
     * @param array  $bind  参数绑定
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1225
     * @return $this
1226
     */
1227
    public function whereOrRaw(string $where, array $bind = [])
1228
    {
1229
        return $this->whereRaw($where, $bind, 'OR');
1230
    }
1231
1232
    /**
1233
     * 分析查询表达式
1234
     * @access protected
1235
     * @param string $logic     查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1236
     * @param mixed  $field     查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1237
     * @param mixed  $op        查询表达式
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1238
     * @param mixed  $condition 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1239
     * @param array  $param     查询参数
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1240
     * @param bool   $strict    严格模式
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1241
     * @return $this
1242
     */
1243
    protected function parseWhereExp(string $logic, $field, $op, $condition, array $param = [], bool $strict = false)
1244
    {
1245
        $logic = strtoupper($logic);
1246
1247
        if (is_string($field) && !empty($this->options['via']) && false === strpos($field, '.')) {
1248
            $field = $this->options['via'] . '.' . $field;
1249
        }
1250
1251
        if ($field instanceof Raw) {
1252
            return $this->whereRaw($field, is_array($op) ? $op : [], $logic);
1253
        } elseif ($strict) {
1254
            // 使用严格模式查询
1255
            if ('=' == $op) {
1256
                $where = $this->whereEq($field, $condition);
1257
            } else {
1258
                $where = [$field, $op, $condition, $logic];
1259
            }
1260
        } elseif (is_array($field)) {
1261
            // 解析数组批量查询
1262
            return $this->parseArrayWhereItems($field, $logic);
1263
        } elseif ($field instanceof Closure) {
1264
            $where = $field;
1265
        } elseif (is_string($field)) {
1266
            if (preg_match('/[,=\<\'\"\(\s]/', $field)) {
1267
                return $this->whereRaw($field, is_array($op) ? $op : [], $logic);
1268
            } elseif (is_string($op) && strtolower($op) == 'exp') {
1269
                $bind = isset($param[2]) && is_array($param[2]) ? $param[2] : [];
1270
                return $this->whereExp($field, $condition, $bind, $logic);
1271
            }
1272
1273
            $where = $this->parseWhereItem($logic, $field, $op, $condition, $param);
1274
        }
1275
1276
        if (!empty($where)) {
1277
            $this->options['where'][$logic][] = $where;
1278
        }
1279
1280
        return $this;
1281
    }
1282
1283
    /**
1284
     * 分析查询表达式
1285
     * @access protected
1286
     * @param string $logic     查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1287
     * @param mixed  $field     查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1288
     * @param mixed  $op        查询表达式
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1289
     * @param mixed  $condition 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1290
     * @param array  $param     查询参数
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1291
     * @return array
1292
     */
1293
    protected function parseWhereItem(string $logic, $field, $op, $condition, array $param = []): array
1294
    {
1295
        if (is_array($op)) {
1296
            // 同一字段多条件查询
1297
            array_unshift($param, $field);
1298
            $where = $param;
1299
        } elseif ($field && is_null($condition)) {
1300
            if (is_string($op) && in_array(strtoupper($op), ['NULL', 'NOTNULL', 'NOT NULL'], true)) {
1301
                // null查询
1302
                $where = [$field, $op, ''];
1303
            } elseif ('=' === $op || is_null($op)) {
1304
                $where = [$field, 'NULL', ''];
1305
            } elseif ('<>' === $op) {
1306
                $where = [$field, 'NOTNULL', ''];
1307
            } else {
1308
                // 字段相等查询
1309
                $where = $this->whereEq($field, $op);
1310
            }
1311
        } elseif (in_array(strtoupper($op), ['EXISTS', 'NOT EXISTS', 'NOTEXISTS'], true)) {
1312
            $where = [$field, $op, is_string($condition) ? new Raw($condition) : $condition];
1313
        } else {
1314
            $where = $field ? [$field, $op, $condition, $param[2] ?? null] : [];
1315
        }
1316
1317
        return $where;
1318
    }
1319
1320
    /**
1321
     * 相等查询的主键处理
1322
     * @access protected
1323
     * @param string $field 字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1324
     * @param mixed  $value 字段值
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1325
     * @return array
1326
     */
1327
    protected function whereEq(string $field, $value): array
1328
    {
1329
        $where = [$field, '=', $value];
1330
        if ($this->getPk() == $field) {
1331
            $this->options['key'] = $value;
1332
        }
1333
1334
        return $where;
1335
    }
1336
1337
    /**
1338
     * 数组批量查询
1339
     * @access protected
1340
     * @param array  $field 批量查询
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1341
     * @param string $logic 查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1342
     * @return $this
1343
     */
1344
    protected function parseArrayWhereItems(array $field, string $logic)
1345
    {
1346
        if (key($field) !== 0) {
1347
            $where = [];
1348
            foreach ($field as $key => $val) {
1349
                if ($val instanceof Raw) {
1350
                    $where[] = [$key, 'exp', $val];
1351
                } else {
1352
                    $where[] = is_null($val) ? [$key, 'NULL', ''] : [$key, is_array($val) ? 'IN' : '=', $val];
1353
                }
1354
            }
1355
        } else {
1356
            // 数组批量查询
1357
            $where = $field;
1358
        }
1359
1360
        if (!empty($where)) {
1361
            $this->options['where'][$logic] = isset($this->options['where'][$logic]) ? array_merge($this->options['where'][$logic], $where) : $where;
1362
        }
1363
1364
        return $this;
1365
    }
1366
1367
    /**
1368
     * 去除某个查询条件
1369
     * @access public
1370
     * @param string $field 查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1371
     * @param string $logic 查询逻辑 and or xor
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1372
     * @return $this
1373
     */
1374
    public function removeWhereField(string $field, string $logic = 'AND')
1375
    {
1376
        $logic = strtoupper($logic);
1377
1378
        if (isset($this->options['where'][$logic])) {
1379
            foreach ($this->options['where'][$logic] as $key => $val) {
1380
                if (is_array($val) && $val[0] == $field) {
1381
                    unset($this->options['where'][$logic][$key]);
1382
                }
1383
            }
1384
        }
1385
1386
        return $this;
1387
    }
1388
1389
    /**
1390
     * 去除查询参数
1391
     * @access public
1392
     * @param string $option 参数名 留空去除所有参数
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1393
     * @return $this
1394
     */
1395
    public function removeOption(string $option = '')
1396
    {
1397
        if ('' === $option) {
1398
            $this->options = [];
1399
            $this->bind    = [];
1400
        } elseif (isset($this->options[$option])) {
1401
            unset($this->options[$option]);
1402
        }
1403
1404
        return $this;
1405
    }
1406
1407
    /**
1408
     * 条件查询
1409
     * @access public
1410
     * @param mixed         $condition 满足条件(支持闭包)
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1411
     * @param Closure|array $query     满足条件后执行的查询表达式(闭包或数组)
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1412
     * @param Closure|array $otherwise 不满足条件后执行
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1413
     * @return $this
1414
     */
1415
    public function when($condition, $query, $otherwise = null)
1416
    {
1417
        if ($condition instanceof Closure) {
1418
            $condition = $condition($this);
1419
        }
1420
1421
        if ($condition) {
1422
            if ($query instanceof Closure) {
1423
                $query($this, $condition);
1424
            } elseif (is_array($query)) {
0 ignored issues
show
introduced by
The condition is_array($query) is always true.
Loading history...
1425
                $this->where($query);
1426
            }
1427
        } elseif ($otherwise) {
1428
            if ($otherwise instanceof Closure) {
1429
                $otherwise($this, $condition);
1430
            } elseif (is_array($otherwise)) {
0 ignored issues
show
introduced by
The condition is_array($otherwise) is always true.
Loading history...
1431
                $this->where($otherwise);
1432
            }
1433
        }
1434
1435
        return $this;
1436
    }
1437
1438
    /**
1439
     * 指定查询数量
1440
     * @access public
1441
     * @param int $offset 起始位置
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1442
     * @param int $length 查询数量
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1443
     * @return $this
1444
     */
1445
    public function limit(int $offset, int $length = null)
1446
    {
1447
        $this->options['limit'] = $offset . ($length ? ',' . $length : '');
1448
1449
        return $this;
1450
    }
1451
1452
    /**
1453
     * 指定分页
1454
     * @access public
1455
     * @param int $page     页数
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1456
     * @param int $listRows 每页数量
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1457
     * @return $this
1458
     */
1459
    public function page(int $page, int $listRows = null)
1460
    {
1461
        $this->options['page'] = [$page, $listRows];
1462
1463
        return $this;
1464
    }
1465
1466
    /**
1467
     * 分页查询
1468
     * @access public
1469
     * @param int|array $listRows 每页数量 数组表示配置参数
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1470
     * @param int|bool  $simple   是否简洁模式或者总记录数
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1471
     * @param array     $config   配置参数
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1472
     * @return Paginator
1473
     * @throws DbException
1474
     */
1475
    public function paginate($listRows = null, $simple = false, $config = [])
1476
    {
1477
        if (is_int($simple)) {
1478
            $total  = $simple;
1479
            $simple = false;
1480
        }
1481
1482
        $defaultConfig = [
1483
            'query'     => [], //url额外参数
1484
            'fragment'  => '', //url锚点
1485
            'var_page'  => 'page', //分页变量
1486
            'list_rows' => 15, //每页数量
1487
        ];
1488
1489
        if (is_array($listRows)) {
1490
            $config   = array_merge($defaultConfig, $listRows);
1491
            $listRows = intval($config['list_rows']);
1492
        } else {
1493
            $config   = array_merge($defaultConfig, $config);
1494
            $listRows = intval($listRows ?: $config['list_rows']);
1495
        }
1496
1497
        $page = isset($config['page']) ? (int) $config['page'] : Paginator::getCurrentPage($config['var_page']);
1498
1499
        $page = $page < 1 ? 1 : $page;
1500
1501
        $config['path'] = $config['path'] ?? Paginator::getCurrentPath();
1502
1503
        if (!isset($total) && !$simple) {
1504
            $options = $this->getOptions();
1505
1506
            unset($this->options['order'], $this->options['limit'], $this->options['page'], $this->options['field']);
1507
1508
            $bind    = $this->bind;
1509
            $total   = $this->count();
1510
            $results = $this->options($options)->bind($bind)->page($page, $listRows)->select();
1511
        } elseif ($simple) {
1512
            $results = $this->limit(($page - 1) * $listRows, $listRows + 1)->select();
1513
            $total   = null;
1514
        } else {
1515
            $results = $this->page($page, $listRows)->select();
1516
        }
1517
1518
        $this->removeOption('limit');
1519
        $this->removeOption('page');
1520
1521
        return Paginator::make($results, $listRows, $page, $total, $simple, $config);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $total does not seem to be defined for all execution paths leading up to this point.
Loading history...
1522
    }
1523
1524
    /**
1525
     * 表达式方式指定当前操作的数据表
1526
     * @access public
1527
     * @param mixed $table 表名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1528
     * @return $this
1529
     */
1530
    public function tableRaw(string $table)
1531
    {
1532
        $this->options['table'] = new Raw($table);
1533
1534
        return $this;
1535
    }
1536
1537
    /**
1538
     * 指定当前操作的数据表
1539
     * @access public
1540
     * @param mixed $table 表名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1541
     * @return $this
1542
     */
1543
    public function table($table)
1544
    {
1545
        if (is_string($table)) {
1546
            if (strpos($table, ')')) {
1547
                // 子查询
1548
            } elseif (false === strpos($table, ',')) {
1549
                if (strpos($table, ' ')) {
1550
                    list($item, $alias) = explode(' ', $table);
1551
                    $table              = [];
1552
                    $this->alias([$item => $alias]);
1553
                    $table[$item] = $alias;
1554
                }
1555
            } else {
1556
                $tables = explode(',', $table);
1557
                $table  = [];
1558
1559
                foreach ($tables as $item) {
1560
                    $item = trim($item);
1561
                    if (strpos($item, ' ')) {
1562
                        list($item, $alias) = explode(' ', $item);
1563
                        $this->alias([$item => $alias]);
1564
                        $table[$item] = $alias;
1565
                    } else {
1566
                        $table[] = $item;
1567
                    }
1568
                }
1569
            }
1570
        } elseif (is_array($table)) {
1571
            $tables = $table;
1572
            $table  = [];
1573
1574
            foreach ($tables as $key => $val) {
1575
                if (is_numeric($key)) {
1576
                    $table[] = $val;
1577
                } else {
1578
                    $this->alias([$key => $val]);
1579
                    $table[$key] = $val;
1580
                }
1581
            }
1582
        }
1583
1584
        $this->options['table'] = $table;
1585
1586
        return $this;
1587
    }
1588
1589
    /**
1590
     * USING支持 用于多表删除
1591
     * @access public
1592
     * @param mixed $using USING
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1593
     * @return $this
1594
     */
1595
    public function using($using)
1596
    {
1597
        $this->options['using'] = $using;
1598
        return $this;
1599
    }
1600
1601
    /**
1602
     * 存储过程调用
1603
     * @access public
1604
     * @param bool $procedure 是否为存储过程查询
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1605
     * @return $this
1606
     */
1607
    public function procedure(bool $procedure = true)
1608
    {
1609
        $this->options['procedure'] = $procedure;
1610
        return $this;
1611
    }
1612
1613
    /**
1614
     * 是否允许返回空数据(或空模型)
1615
     * @access public
1616
     * @param bool $allowEmpty 是否允许为空
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1617
     * @return $this
1618
     */
1619
    public function allowEmpty(bool $allowEmpty = true)
1620
    {
1621
        $this->options['allow_empty'] = $allowEmpty;
1622
        return $this;
1623
    }
1624
1625
    /**
1626
     * 指定排序 order('id','desc') 或者 order(['id'=>'desc','create_time'=>'desc'])
1627
     * @access public
1628
     * @param string|array|Raw $field 排序字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1629
     * @param string           $order 排序
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1630
     * @return $this
1631
     */
1632
    public function order($field, string $order = '')
1633
    {
1634
        if (empty($field)) {
1635
            return $this;
1636
        } elseif ($field instanceof Raw) {
1637
            $this->options['order'][] = $field;
1638
            return $this;
1639
        }
1640
1641
        if (is_string($field)) {
1642
            if (!empty($this->options['via'])) {
1643
                $field = $this->options['via'] . '.' . $field;
1644
            }
1645
            if (strpos($field, ',')) {
1646
                $field = array_map('trim', explode(',', $field));
1647
            } else {
1648
                $field = empty($order) ? $field : [$field => $order];
1649
            }
1650
        } elseif (!empty($this->options['via'])) {
1651
            foreach ($field as $key => $val) {
1652
                if (is_numeric($key)) {
1653
                    $field[$key] = $this->options['via'] . '.' . $val;
1654
                } else {
1655
                    $field[$this->options['via'] . '.' . $key] = $val;
1656
                    unset($field[$key]);
1657
                }
1658
            }
1659
        }
1660
1661
        if (!isset($this->options['order'])) {
1662
            $this->options['order'] = [];
1663
        }
1664
1665
        if (is_array($field)) {
1666
            $this->options['order'] = array_merge($this->options['order'], $field);
1667
        } else {
1668
            $this->options['order'][] = $field;
1669
        }
1670
1671
        return $this;
1672
    }
1673
1674
    /**
1675
     * 表达式方式指定Field排序
1676
     * @access public
1677
     * @param string $field 排序字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1678
     * @param array  $bind  参数绑定
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1679
     * @return $this
1680
     */
1681
    public function orderRaw(string $field, array $bind = [])
1682
    {
1683
        if (!empty($bind)) {
1684
            $this->bindParams($field, $bind);
1685
        }
1686
1687
        $this->options['order'][] = new Raw($field);
1688
1689
        return $this;
1690
    }
1691
1692
    /**
1693
     * 指定Field排序 orderField('id',[1,2,3],'desc')
1694
     * @access public
1695
     * @param string $field  排序字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1696
     * @param array  $values 排序值
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1697
     * @param string $order  排序 desc/asc
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1698
     * @return $this
1699
     */
1700
    public function orderField(string $field, array $values, string $order = '')
1701
    {
1702
        if (!empty($values)) {
1703
            $values['sort'] = $order;
1704
1705
            $this->options['order'][$field] = $values;
1706
        }
1707
1708
        return $this;
1709
    }
1710
1711
    /**
1712
     * 随机排序
1713
     * @access public
1714
     * @return $this
1715
     */
1716
    public function orderRand()
1717
    {
1718
        $this->options['order'][] = '[rand]';
1719
        return $this;
1720
    }
1721
1722
    /**
1723
     * 查询缓存
1724
     * @access public
1725
     * @param mixed             $key    缓存key
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1726
     * @param integer|\DateTime $expire 缓存有效期
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1727
     * @param string            $tag    缓存标签
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1728
     * @return $this
1729
     */
1730
    public function cache($key = true, $expire = null, string $tag = null)
1731
    {
1732
        if (false === $key) {
1733
            return $this;
1734
        }
1735
1736
        if ($key instanceof \DateTimeInterface || (is_int($key) && is_null($expire))) {
1737
            $expire = $key;
1738
            $key    = true;
1739
        }
1740
1741
        $this->options['cache'] = [$key, $expire, $tag];
1742
1743
        return $this;
1744
    }
1745
1746
    /**
1747
     * 指定group查询
1748
     * @access public
1749
     * @param string|array $group GROUP
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1750
     * @return $this
1751
     */
1752
    public function group($group)
1753
    {
1754
        $this->options['group'] = $group;
1755
        return $this;
1756
    }
1757
1758
    /**
1759
     * 指定having查询
1760
     * @access public
1761
     * @param string $having having
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1762
     * @return $this
1763
     */
1764
    public function having(string $having)
1765
    {
1766
        $this->options['having'] = $having;
1767
        return $this;
1768
    }
1769
1770
    /**
1771
     * 指定查询lock
1772
     * @access public
1773
     * @param bool|string $lock 是否lock
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1774
     * @return $this
1775
     */
1776
    public function lock($lock = false)
1777
    {
1778
        $this->options['lock'] = $lock;
1779
1780
        if ($lock) {
1781
            $this->options['master'] = true;
1782
        }
1783
1784
        return $this;
1785
    }
1786
1787
    /**
1788
     * 指定distinct查询
1789
     * @access public
1790
     * @param bool|string $distinct 是否唯一
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1791
     * @return $this
1792
     */
1793
    public function distinct($distinct = true)
1794
    {
1795
        $this->options['distinct'] = $distinct;
1796
        return $this;
1797
    }
1798
1799
    /**
1800
     * 指定数据表别名
1801
     * @access public
1802
     * @param array|string $alias 数据表别名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1803
     * @return $this
1804
     */
1805
    public function alias($alias)
1806
    {
1807
        if (is_array($alias)) {
1808
            $this->options['alias'] = $alias;
1809
        } else {
1810
            $table = $this->getTable();
1811
1812
            $this->options['alias'][$table] = $alias;
1813
        }
1814
1815
        return $this;
1816
    }
1817
1818
    /**
1819
     * 指定强制索引
1820
     * @access public
1821
     * @param string $force 索引名称
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1822
     * @return $this
1823
     */
1824
    public function force(string $force)
1825
    {
1826
        $this->options['force'] = $force;
1827
        return $this;
1828
    }
1829
1830
    /**
1831
     * 查询注释
1832
     * @access public
1833
     * @param string $comment 注释
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1834
     * @return $this
1835
     */
1836
    public function comment(string $comment)
1837
    {
1838
        $this->options['comment'] = $comment;
1839
        return $this;
1840
    }
1841
1842
    /**
1843
     * 获取执行的SQL语句而不进行实际的查询
1844
     * @access public
1845
     * @param bool $fetch 是否返回sql
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1846
     * @return $this|Fetch
1847
     */
1848
    public function fetchSql(bool $fetch = true)
1849
    {
1850
        $this->options['fetch_sql'] = $fetch;
1851
1852
        if ($fetch) {
1853
            return new Fetch($this);
1854
        }
1855
1856
        return $this;
1857
    }
1858
1859
    /**
1860
     * 设置是否返回数据集对象
1861
     * @access public
1862
     * @param bool|string $collection 是否返回数据集对象
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1863
     * @return $this
1864
     */
1865
    public function fetchCollection($collection = true)
1866
    {
1867
        $this->options['collection'] = $collection;
1868
        return $this;
1869
    }
1870
1871
    /**
1872
     * 设置是否返回数组
1873
     * @access public
1874
     * @param bool $asArray 是否返回数组
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1875
     * @return $this
1876
     */
1877
    public function fetchArray(bool $asArray = true)
1878
    {
1879
        $this->options['array'] = $asArray;
1880
        return $this;
1881
    }
1882
1883
    /**
1884
     * 设置从主服务器读取数据
1885
     * @access public
1886
     * @param bool $readMaster 是否从主服务器读取
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1887
     * @return $this
1888
     */
1889
    public function master(bool $readMaster = true)
1890
    {
1891
        $this->options['master'] = $readMaster;
1892
        return $this;
1893
    }
1894
1895
    /**
1896
     * 设置是否严格检查字段名
1897
     * @access public
1898
     * @param bool $strict 是否严格检查字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1899
     * @return $this
1900
     */
1901
    public function strict(bool $strict = true)
1902
    {
1903
        $this->options['strict'] = $strict;
1904
        return $this;
1905
    }
1906
1907
    /**
1908
     * 设置查询数据不存在是否抛出异常
1909
     * @access public
1910
     * @param bool $fail 数据不存在是否抛出异常
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1911
     * @return $this
1912
     */
1913
    public function failException(bool $fail = true)
1914
    {
1915
        $this->options['fail'] = $fail;
1916
        return $this;
1917
    }
1918
1919
    /**
1920
     * 设置自增序列名
1921
     * @access public
1922
     * @param string $sequence 自增序列名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1923
     * @return $this
1924
     */
1925
    public function sequence(string $sequence = null)
1926
    {
1927
        $this->options['sequence'] = $sequence;
1928
        return $this;
1929
    }
1930
1931
    /**
1932
     * 设置是否REPLACE
1933
     * @access public
1934
     * @param bool $replace 是否使用REPLACE写入数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1935
     * @return $this
1936
     */
1937
    public function replace(bool $replace = true)
1938
    {
1939
        $this->options['replace'] = $replace;
1940
        return $this;
1941
    }
1942
1943
    /**
1944
     * 设置当前查询所在的分区
1945
     * @access public
1946
     * @param string|array $partition 分区名称
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1947
     * @return $this
1948
     */
1949
    public function partition($partition)
1950
    {
1951
        $this->options['partition'] = $partition;
1952
        return $this;
1953
    }
1954
1955
    /**
1956
     * 设置DUPLICATE
1957
     * @access public
1958
     * @param array|string|Raw $duplicate DUPLICATE信息
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1959
     * @return $this
1960
     */
1961
    public function duplicate($duplicate)
1962
    {
1963
        $this->options['duplicate'] = $duplicate;
1964
        return $this;
1965
    }
1966
1967
    /**
1968
     * 设置查询的额外参数
1969
     * @access public
1970
     * @param string $extra 额外信息
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1971
     * @return $this
1972
     */
1973
    public function extra(string $extra)
1974
    {
1975
        $this->options['extra'] = $extra;
1976
        return $this;
1977
    }
1978
1979
    /**
1980
     * 设置需要隐藏的输出属性
1981
     * @access public
1982
     * @param array $hidden 需要隐藏的字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1983
     * @return $this
1984
     */
1985
    public function hidden(array $hidden)
1986
    {
1987
        $this->options['hidden'] = $hidden;
1988
        return $this;
1989
    }
1990
1991
    /**
1992
     * 设置需要输出的属性
1993
     * @access public
1994
     * @param array $visible 需要输出的属性
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
1995
     * @return $this
1996
     */
1997
    public function visible(array $visible)
1998
    {
1999
        $this->options['visible'] = $visible;
2000
        return $this;
2001
    }
2002
2003
    /**
2004
     * 设置需要追加输出的属性
2005
     * @access public
2006
     * @param array $append 需要追加的属性
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2007
     * @return $this
2008
     */
2009
    public function append(array $append)
2010
    {
2011
        $this->options['append'] = $append;
2012
        return $this;
2013
    }
2014
2015
    /**
2016
     * 设置JSON字段信息
2017
     * @access public
2018
     * @param array $json  JSON字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2019
     * @param bool  $assoc 是否取出数组
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2020
     * @return $this
2021
     */
2022
    public function json(array $json = [], bool $assoc = false)
2023
    {
2024
        $this->options['json']       = $json;
2025
        $this->options['json_assoc'] = $assoc;
2026
        return $this;
2027
    }
2028
2029
    /**
0 ignored issues
show
Coding Style introduced by
Parameter ...$args should have a doc-comment as per coding-style.
Loading history...
2030
     * 添加查询范围
2031
     * @access public
2032
     * @param array|string|Closure $scope 查询范围定义
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2033
     * @param array                $args  参数
1 ignored issue
show
Coding Style introduced by
Doc comment for parameter $args does not match actual variable name ...$args
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2034
     * @return $this
2035
     */
2036
    public function scope($scope, ...$args)
2037
    {
2038
        // 查询范围的第一个参数始终是当前查询对象
2039
        array_unshift($args, $this);
2040
2041
        if ($scope instanceof Closure) {
2042
            call_user_func_array($scope, $args);
2043
            return $this;
2044
        }
2045
2046
        if (is_string($scope)) {
2047
            $scope = explode(',', $scope);
2048
        }
2049
2050
        if ($this->model) {
2051
            // 检查模型类的查询范围方法
2052
            foreach ($scope as $name) {
2053
                $method = 'scope' . trim($name);
2054
2055
                if (method_exists($this->model, $method)) {
2056
                    call_user_func_array([$this->model, $method], $args);
2057
                }
2058
            }
2059
        }
2060
2061
        return $this;
2062
    }
2063
2064
    /**
2065
     * 指定数据表主键
2066
     * @access public
2067
     * @param string $pk 主键
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2068
     * @return $this
2069
     */
2070
    public function pk(string $pk)
2071
    {
2072
        $this->pk = $pk;
2073
        return $this;
2074
    }
2075
2076
    /**
2077
     * 添加日期或者时间查询规则
2078
     * @access public
2079
     * @param string       $name 时间表达式
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2080
     * @param string|array $rule 时间范围
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2081
     * @return $this
2082
     */
2083
    public function timeRule(string $name, $rule)
2084
    {
2085
        $this->timeRule[$name] = $rule;
2086
        return $this;
2087
    }
2088
2089
    /**
2090
     * 查询日期或者时间
2091
     * @access public
2092
     * @param string       $field 日期字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2093
     * @param string       $op    比较运算符或者表达式
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2094
     * @param string|array $range 比较范围
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2095
     * @param string       $logic AND OR
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2096
     * @return $this
2097
     */
2098
    public function whereTime(string $field, string $op, $range = null, string $logic = 'AND')
2099
    {
2100
        if (is_null($range) && isset($this->timeRule[$op])) {
2101
            $range = $this->timeRule[$op];
2102
            $op    = 'between';
2103
        }
2104
2105
        return $this->parseWhereExp($logic, $field, strtolower($op) . ' time', $range, [], true);
2106
    }
2107
2108
    /**
2109
     * 查询某个时间间隔数据
2110
     * @access protected
2111
     * @param string $field    日期字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2112
     * @param string $start    开始时间
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2113
     * @param string $interval 时间间隔单位
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2114
     * @param string $logic    AND OR
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2115
     * @return $this
2116
     */
2117
    protected function whereTimeInterval(string $field, string $start, string $interval = 'day', string $logic = 'AND')
2118
    {
2119
        $startTime = strtotime($start);
2120
        $endTime   = strtotime('+1 ' . $interval, $startTime);
2121
2122
        return $this->whereTime($field, 'between', [$startTime, $endTime], $logic);
2123
    }
2124
2125
    /**
2126
     * 查询月数据 whereMonth('time_field', '2018-1')
2127
     * @access public
2128
     * @param string $field 日期字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2129
     * @param string $month 月份信息
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2130
     * @param string $logic AND OR
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2131
     * @return $this
2132
     */
2133
    public function whereMonth(string $field, string $month = 'this month', string $logic = 'AND')
2134
    {
2135
        if (in_array($month, ['this month', 'last month'])) {
2136
            $month = date('Y-m', strtotime($month));
2137
        }
2138
2139
        return $this->whereTimeInterval($field, $month, 'month', $logic);
2140
    }
2141
2142
    /**
2143
     * 查询年数据 whereYear('time_field', '2018')
2144
     * @access public
2145
     * @param string $field 日期字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2146
     * @param string $year  年份信息
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2147
     * @param string $logic AND OR
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2148
     * @return $this
2149
     */
2150
    public function whereYear(string $field, string $year = 'this year', string $logic = 'AND')
2151
    {
2152
        if (in_array($year, ['this year', 'last year'])) {
2153
            $year = date('Y', strtotime($year));
2154
        }
2155
2156
        return $this->whereTimeInterval($field, $year . '-1-1', 'year', $logic);
2157
    }
2158
2159
    /**
2160
     * 查询日数据 whereDay('time_field', '2018-1-1')
2161
     * @access public
2162
     * @param string $field 日期字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2163
     * @param string $day   日期信息
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2164
     * @param string $logic AND OR
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2165
     * @return $this
2166
     */
2167
    public function whereDay(string $field, string $day = 'today', string $logic = 'AND')
2168
    {
2169
        if (in_array($day, ['today', 'yesterday'])) {
2170
            $day = date('Y-m-d', strtotime($day));
2171
        }
2172
2173
        return $this->whereTimeInterval($field, $day, 'day', $logic);
2174
    }
2175
2176
    /**
2177
     * 查询日期或者时间范围 whereBetweenTime('time_field', '2018-1-1','2018-1-15')
2178
     * @access public
2179
     * @param string     $field     日期字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2180
     * @param string|int $startTime 开始时间
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2181
     * @param string|int $endTime   结束时间
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2182
     * @param string     $logic     AND OR
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2183
     * @return $this
2184
     */
2185
    public function whereBetweenTime(string $field, $startTime, $endTime, string $logic = 'AND')
2186
    {
2187
        return $this->whereTime($field, 'between', [$startTime, $endTime], $logic);
2188
    }
2189
2190
    /**
2191
     * 查询日期或者时间范围 whereNotBetweenTime('time_field', '2018-1-1','2018-1-15')
2192
     * @access public
2193
     * @param string     $field     日期字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2194
     * @param string|int $startTime 开始时间
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2195
     * @param string|int $endTime   结束时间
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2196
     * @return $this
2197
     */
2198
    public function whereNotBetweenTime(string $field, $startTime, $endTime)
2199
    {
2200
        return $this->whereTime($field, '<', $startTime)
2201
            ->whereTime($field, '>', $endTime);
2202
    }
2203
2204
    /**
2205
     * 查询当前时间在两个时间字段范围 whereBetweenTimeField('start_time', 'end_time')
2206
     * @access public
2207
     * @param string $startField 开始时间字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2208
     * @param string $endField   结束时间字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2209
     * @return $this
2210
     */
2211
    public function whereBetweenTimeField(string $startField, string $endField)
2212
    {
2213
        return $this->whereTime($startField, '<=', time())
2214
            ->whereTime($endField, '>=', time());
2215
    }
2216
2217
    /**
2218
     * 查询当前时间不在两个时间字段范围 whereNotBetweenTimeField('start_time', 'end_time')
2219
     * @access public
2220
     * @param string $startField 开始时间字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2221
     * @param string $endField   结束时间字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2222
     * @return $this
2223
     */
2224
    public function whereNotBetweenTimeField(string $startField, string $endField)
2225
    {
2226
        return $this->whereTime($startField, '>', time())
2227
            ->whereTime($endField, '<', time(), 'OR');
2228
    }
2229
2230
    /**
2231
     * 获取当前数据表的主键
2232
     * @access public
2233
     * @return string|array
2234
     */
2235
    public function getPk()
2236
    {
2237
        if (!empty($this->pk)) {
2238
            $pk = $this->pk;
2239
        } else {
2240
            $this->pk = $pk = $this->connection->getPk($this->getTable());
2241
        }
2242
2243
        return $pk;
2244
    }
2245
2246
    /**
2247
     * 批量参数绑定
2248
     * @access public
2249
     * @param array $value 绑定变量值
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2250
     * @return $this
2251
     */
2252
    public function bind(array $value)
2253
    {
2254
        $this->bind = array_merge($this->bind, $value);
2255
        return $this;
2256
    }
2257
2258
    /**
2259
     * 单个参数绑定
2260
     * @access public
2261
     * @param mixed   $value 绑定变量值
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2262
     * @param integer $type  绑定类型
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2263
     * @param string  $name  绑定标识
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2264
     * @return string
2265
     */
2266
    public function bindValue($value, int $type = null, string $name = null)
2267
    {
2268
        $name = $name ?: 'ThinkBind_' . (count($this->bind) + 1) . '_';
2269
2270
        $this->bind[$name] = [$value, $type ?: PDO::PARAM_STR];
2271
        return $name;
2272
    }
2273
2274
    /**
2275
     * 检测参数是否已经绑定
2276
     * @access public
2277
     * @param string $key 参数名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2278
     * @return bool
2279
     */
2280
    public function isBind($key)
2281
    {
2282
        return isset($this->bind[$key]);
2283
    }
2284
2285
    /**
2286
     * 参数绑定
2287
     * @access public
2288
     * @param string $sql  绑定的sql表达式
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2289
     * @param array  $bind 参数绑定
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2290
     * @return void
2291
     */
2292
    protected function bindParams(string &$sql, array $bind = []): void
2293
    {
2294
        foreach ($bind as $key => $value) {
2295
            if (is_array($value)) {
2296
                $name = $this->bindValue($value[0], $value[1], $value[2] ?? null);
2297
            } else {
2298
                $name = $this->bindValue($value);
2299
            }
2300
2301
            if (is_numeric($key)) {
2302
                $sql = substr_replace($sql, ':' . $name, strpos($sql, '?'), 1);
2303
            } else {
2304
                $sql = str_replace(':' . $key, ':' . $name, $sql);
2305
            }
2306
        }
2307
    }
2308
2309
    /**
2310
     * 查询参数批量赋值
2311
     * @access protected
2312
     * @param array $options 表达式参数
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2313
     * @return $this
2314
     */
2315
    protected function options(array $options)
2316
    {
2317
        $this->options = $options;
2318
        return $this;
2319
    }
2320
2321
    /**
2322
     * 获取当前的查询参数
2323
     * @access public
2324
     * @param string $name 参数名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2325
     * @return mixed
2326
     */
2327
    public function getOptions(string $name = '')
2328
    {
2329
        if ('' === $name) {
2330
            return $this->options;
2331
        }
2332
2333
        return $this->options[$name] ?? null;
2334
    }
2335
2336
    /**
2337
     * 设置当前的查询参数
2338
     * @access public
2339
     * @param string $option 参数名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2340
     * @param mixed  $value  参数值
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2341
     * @return $this
2342
     */
2343
    public function setOption(string $option, $value)
2344
    {
2345
        $this->options[$option] = $value;
2346
        return $this;
2347
    }
2348
2349
    /**
2350
     * 设置关联查询
2351
     * @access public
2352
     * @param array $relation 关联名称
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2353
     * @return $this
2354
     */
2355
    public function relation(array $relation)
2356
    {
2357
        if (!empty($relation)) {
2358
            $this->options['relation'] = $relation;
2359
        }
2360
2361
        return $this;
2362
    }
2363
2364
    /**
2365
     * 设置关联查询JOIN预查询
2366
     * @access public
2367
     * @param array|string $with 关联方法名称
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2368
     * @return $this
2369
     */
2370
    public function with($with)
2371
    {
2372
        if (!empty($with)) {
2373
            $this->options['with'] = (array) $with;
2374
        }
2375
2376
        return $this;
2377
    }
2378
2379
    /**
2380
     * 关联预载入 JOIN方式
2381
     * @access protected
2382
     * @param array|string $with     关联方法名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2383
     * @param string       $joinType JOIN方式
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2384
     * @return $this
2385
     */
2386
    public function withJoin($with, string $joinType = '')
2387
    {
2388
        if (empty($with)) {
2389
            return $this;
2390
        }
2391
2392
        $first = true;
2393
2394
        /** @var Model $class */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
2395
        $class = $this->model;
2396
        foreach ((array) $with as $key => $relation) {
2397
            $closure = null;
2398
            $field   = true;
2399
2400
            if ($relation instanceof Closure) {
2401
                // 支持闭包查询过滤关联条件
2402
                $closure  = $relation;
2403
                $relation = $key;
2404
            } elseif (is_array($relation)) {
2405
                $field    = $relation;
2406
                $relation = $key;
2407
            } elseif (is_string($relation) && strpos($relation, '.')) {
2408
                $relation = strstr($relation, '.', true);
2409
            }
2410
2411
            /** @var Relation $model */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
2412
            $relation = App::parseName($relation, 1, false);
2413
            $model    = $class->$relation();
2414
2415
            if ($model instanceof OneToOne) {
2416
                $model->eagerly($this, $relation, $field, $joinType, $closure, $first);
2417
                $first = false;
2418
            } else {
2419
                // 不支持其它关联
2420
                unset($with[$key]);
2421
            }
2422
        }
2423
2424
        $this->via();
2425
2426
        $this->options['with_join'] = $with;
2427
2428
        return $this;
2429
    }
2430
2431
    /**
2432
     * 设置数据字段获取器
2433
     * @access public
2434
     * @param string|array $name     字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2435
     * @param callable     $callback 闭包获取器
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2436
     * @return $this
2437
     */
2438
    public function withAttr($name, callable $callback)
2439
    {
2440
        if (is_array($name)) {
2441
            $this->options['with_attr'] = $name;
2442
        } else {
2443
            $this->options['with_attr'][$name] = $callback;
2444
        }
2445
2446
        return $this;
2447
    }
2448
2449
    /**
2450
     * 使用搜索器条件搜索字段
2451
     * @access public
2452
     * @param array  $fields 搜索字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2453
     * @param array  $data   搜索数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2454
     * @param string $prefix 字段前缀标识
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2455
     * @return $this
2456
     */
2457
    public function withSearch(array $fields, array $data = [], string $prefix = '')
2458
    {
2459
        foreach ($fields as $key => $field) {
2460
            if ($field instanceof Closure) {
2461
                $field($this, $data[$key] ?? null, $data, $prefix);
2462
            } elseif ($this->model) {
2463
                // 检测搜索器
2464
                $fieldName = is_numeric($key) ? $field : $key;
2465
                $method    = 'search' . App::parseName($fieldName, 1) . 'Attr';
2466
2467
                if (method_exists($this->model, $method)) {
2468
                    $this->model->$method($this, $data[$field] ?? null, $data, $prefix);
2469
                }
2470
            }
2471
        }
2472
2473
        return $this;
2474
    }
2475
2476
    /**
2477
     * 关联统计
2478
     * @access protected
2479
     * @param array|string $relations 关联方法名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2480
     * @param string       $aggregate 聚合查询方法
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2481
     * @param string       $field     字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2482
     * @param bool         $subQuery  是否使用子查询
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2483
     * @return $this
2484
     */
2485
    protected function withAggregate($relations, string $aggregate = 'count', $field = '*', bool $subQuery = true)
2486
    {
2487
        if (!$subQuery) {
2488
            $this->options['with_count'][] = [$relations, $aggregate, $field];
2489
        } else {
2490
            if (!isset($this->options['field'])) {
2491
                $this->field('*');
2492
            }
2493
2494
            foreach ((array) $relations as $key => $relation) {
2495
                $closure = $aggregateField = null;
2496
2497
                if ($relation instanceof Closure) {
2498
                    $closure  = $relation;
2499
                    $relation = $key;
2500
                } elseif (!is_int($key)) {
2501
                    $aggregateField = $relation;
2502
                    $relation       = $key;
2503
                }
2504
2505
                $relation = App::parseName($relation, 1, false);
2506
2507
                $count = '(' . $this->model->$relation()->getRelationCountQuery($closure, $aggregate, $field, $aggregateField) . ')';
2508
2509
                if (empty($aggregateField)) {
2510
                    $aggregateField = App::parseName($relation) . '_' . $aggregate;
2511
                }
2512
2513
                $this->field([$count => $aggregateField]);
2514
            }
2515
        }
2516
2517
        return $this;
2518
    }
2519
2520
    /**
2521
     * 关联统计
2522
     * @access public
2523
     * @param string|array $relation 关联方法名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2524
     * @param bool         $subQuery 是否使用子查询
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2525
     * @return $this
2526
     */
2527
    public function withCount($relation, bool $subQuery = true)
2528
    {
2529
        return $this->withAggregate($relation, 'count', '*', $subQuery);
2530
    }
2531
2532
    /**
2533
     * 关联统计Sum
2534
     * @access public
2535
     * @param string|array $relation 关联方法名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2536
     * @param string       $field    字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2537
     * @param bool         $subQuery 是否使用子查询
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2538
     * @return $this
2539
     */
2540
    public function withSum($relation, string $field, bool $subQuery = true)
2541
    {
2542
        return $this->withAggregate($relation, 'sum', $field, $subQuery);
2543
    }
2544
2545
    /**
2546
     * 关联统计Max
2547
     * @access public
2548
     * @param string|array $relation 关联方法名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2549
     * @param string       $field    字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2550
     * @param bool         $subQuery 是否使用子查询
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2551
     * @return $this
2552
     */
2553
    public function withMax($relation, string $field, bool $subQuery = true)
2554
    {
2555
        return $this->withAggregate($relation, 'max', $field, $subQuery);
2556
    }
2557
2558
    /**
2559
     * 关联统计Min
2560
     * @access public
2561
     * @param string|array $relation 关联方法名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2562
     * @param string       $field    字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2563
     * @param bool         $subQuery 是否使用子查询
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2564
     * @return $this
2565
     */
2566
    public function withMin($relation, string $field, bool $subQuery = true)
2567
    {
2568
        return $this->withAggregate($relation, 'min', $field, $subQuery);
2569
    }
2570
2571
    /**
2572
     * 关联统计Avg
2573
     * @access public
2574
     * @param string|array $relation 关联方法名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2575
     * @param string       $field    字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2576
     * @param bool         $subQuery 是否使用子查询
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2577
     * @return $this
2578
     */
2579
    public function withAvg($relation, string $field, bool $subQuery = true)
2580
    {
2581
        return $this->withAggregate($relation, 'avg', $field, $subQuery);
2582
    }
2583
2584
    /**
2585
     * 关联预加载中 获取关联指定字段值
2586
     * example:
2587
     * Model::with(['relation' => function($query){
2588
     *     $query->withField("id,name");
2589
     * }])
2590
     *
2591
     * @access public
2592
     * @param string|array $field 指定获取的字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2593
     * @return $this
2594
     */
2595
    public function withField($field)
2596
    {
2597
        $this->options['with_field'] = $field;
2598
2599
        return $this;
2600
    }
2601
2602
    /**
2603
     * 设置当前字段添加的表别名
2604
     * @access public
2605
     * @param string $via 临时表别名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2606
     * @return $this
2607
     */
2608
    public function via(string $via = '')
2609
    {
2610
        $this->options['via'] = $via;
2611
2612
        return $this;
2613
    }
2614
2615
    /**
2616
     * 保存记录 自动判断insert或者update
2617
     * @access public
2618
     * @param array $data        数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2619
     * @param bool  $forceInsert 是否强制insert
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2620
     * @return integer
2621
     */
2622
    public function save(array $data = [], bool $forceInsert = false)
2623
    {
2624
        if ($forceInsert) {
2625
            return $this->insert($data);
2626
        }
2627
2628
        $this->options['data'] = array_merge($this->options['data'] ?? [], $data);
2629
2630
        if (!empty($this->options['where'])) {
2631
            $isUpdate = true;
2632
        } else {
2633
            $isUpdate = $this->parseUpdateData($this->options['data']);
2634
        }
2635
2636
        return $isUpdate ? $this->update() : $this->insert();
2637
    }
2638
2639
    /**
2640
     * 插入记录
2641
     * @access public
2642
     * @param array   $data         数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2643
     * @param boolean $getLastInsID 返回自增主键
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2644
     * @return integer|string
2645
     */
2646
    public function insert(array $data = [], bool $getLastInsID = false)
2647
    {
2648
        if (!empty($data)) {
2649
            $this->options['data'] = $data;
2650
        }
2651
2652
        return $this->connection->insert($this, $getLastInsID);
2653
    }
2654
2655
    /**
2656
     * 插入记录并获取自增ID
2657
     * @access public
2658
     * @param array $data 数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2659
     * @return integer|string
2660
     */
2661
    public function insertGetId(array $data)
2662
    {
2663
        return $this->insert($data, true);
2664
    }
2665
2666
    /**
2667
     * 批量插入记录
2668
     * @access public
2669
     * @param array   $dataSet 数据集
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2670
     * @param integer $limit   每次写入数据限制
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2671
     * @return integer
2672
     */
2673
    public function insertAll(array $dataSet = [], int $limit = 0): int
2674
    {
2675
        if (empty($dataSet)) {
2676
            $dataSet = $this->options['data'] ?? [];
2677
        }
2678
2679
        if (empty($limit) && !empty($this->options['limit']) && is_numeric($this->options['limit'])) {
2680
            $limit = (int) $this->options['limit'];
2681
        }
2682
2683
        return $this->connection->insertAll($this, $dataSet, $limit);
2684
    }
2685
2686
    /**
2687
     * 通过Select方式插入记录
2688
     * @access public
2689
     * @param array  $fields 要插入的数据表字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2690
     * @param string $table  要插入的数据表名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2691
     * @return integer
2692
     * @throws PDOException
2693
     */
2694
    public function selectInsert(array $fields, string $table): int
2695
    {
2696
        return $this->connection->selectInsert($this, $fields, $table);
2697
    }
2698
2699
    /**
2700
     * 更新记录
2701
     * @access public
2702
     * @param mixed $data 数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2703
     * @return integer
2704
     * @throws Exception
2705
     * @throws PDOException
2706
     */
2707
    public function update(array $data = []): int
2708
    {
2709
        if (!empty($data)) {
2710
            $this->options['data'] = array_merge($this->options['data'] ?? [], $data);
2711
        }
2712
2713
        if (empty($this->options['where'])) {
2714
            $this->parseUpdateData($this->options['data']);
2715
        }
2716
2717
        if (empty($this->options['where']) && $this->model) {
2718
            $this->where($this->model->getWhere());
2719
        }
2720
2721
        if (empty($this->options['where'])) {
2722
            // 如果没有任何更新条件则不执行
2723
            throw new Exception('miss update condition');
2724
        }
2725
2726
        return $this->connection->update($this);
2727
    }
2728
2729
    /**
2730
     * 删除记录
2731
     * @access public
2732
     * @param mixed $data 表达式 true 表示强制删除
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2733
     * @return int
2734
     * @throws Exception
2735
     * @throws PDOException
2736
     */
2737
    public function delete($data = null): int
2738
    {
2739
        if (!is_null($data) && true !== $data) {
2740
            // AR模式分析主键条件
2741
            $this->parsePkWhere($data);
2742
        }
2743
2744
        if (empty($this->options['where']) && $this->model) {
2745
            $this->where($this->model->getWhere());
2746
        }
2747
2748
        if (true !== $data && empty($this->options['where'])) {
2749
            // 如果条件为空 不进行删除操作 除非设置 1=1
2750
            throw new Exception('delete without condition');
2751
        }
2752
2753
        if (!empty($this->options['soft_delete'])) {
2754
            // 软删除
2755
            list($field, $condition) = $this->options['soft_delete'];
2756
            if ($condition) {
2757
                unset($this->options['soft_delete']);
2758
                $this->options['data'] = [$field => $condition];
2759
2760
                return $this->connection->update($this);
2761
            }
2762
        }
2763
2764
        $this->options['data'] = $data;
2765
2766
        return $this->connection->delete($this);
2767
    }
2768
2769
    /**
2770
     * 执行查询但只返回PDOStatement对象
2771
     * @access public
2772
     * @return PDOStatement
2773
     */
2774
    public function getPdo(): PDOStatement
2775
    {
2776
        return $this->connection->pdo($this);
2777
    }
2778
2779
    /**
2780
     * 使用游标查找记录
2781
     * @access public
2782
     * @param mixed $data 数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2783
     * @return \Generator
2784
     */
2785
    public function cursor($data = null)
2786
    {
2787
        if (!is_null($data)) {
2788
            // 主键条件分析
2789
            $this->parsePkWhere($data);
2790
        }
2791
2792
        $this->options['data'] = $data;
2793
2794
        $connection = clone $this->connection;
2795
2796
        return $connection->cursor($this);
2797
    }
2798
2799
    /**
2800
     * 查找记录
2801
     * @access public
2802
     * @param mixed $data 数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2803
     * @return Collection|array|ModelCollection
2804
     * @throws DbException
2805
     * @throws ModelNotFoundException
2806
     * @throws DataNotFoundException
2807
     */
2808
    public function select($data = null)
2809
    {
2810
        if (!is_null($data)) {
2811
            // 主键条件分析
2812
            $this->parsePkWhere($data);
2813
        }
2814
2815
        $resultSet = $this->connection->select($this);
2816
2817
        // 返回结果处理
2818
        if (!empty($this->options['fail']) && count($resultSet) == 0) {
2819
            $this->throwNotFound();
2820
        }
2821
2822
        // 数据列表读取后的处理
2823
        if (!empty($this->model) && empty($this->options['array'])) {
2824
            // 生成模型对象
2825
            $resultSet = $this->resultSetToModelCollection($resultSet);
2826
        } else {
2827
            $this->resultSet($resultSet);
2828
        }
2829
2830
        return $resultSet;
2831
    }
2832
2833
    /**
2834
     * 查询数据转换为模型数据集对象
2835
     * @access protected
2836
     * @param array $resultSet 数据集
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2837
     * @return ModelCollection
2838
     */
2839
    protected function resultSetToModelCollection(array $resultSet): ModelCollection
2840
    {
2841
        if (!empty($this->options['collection']) && is_string($this->options['collection'])) {
2842
            $collection = $this->options['collection'];
2843
        }
2844
2845
        if (empty($resultSet)) {
2846
            return $this->model->toCollection([], $collection ?? null);
2847
        }
2848
2849
        // 检查动态获取器
2850
        if (!empty($this->options['with_attr'])) {
2851
            foreach ($this->options['with_attr'] as $name => $val) {
2852
                if (strpos($name, '.')) {
2853
                    list($relation, $field) = explode('.', $name);
2854
2855
                    $withRelationAttr[$relation][$field] = $val;
2856
                    unset($this->options['with_attr'][$name]);
2857
                }
2858
            }
2859
        }
2860
2861
        $withRelationAttr = $withRelationAttr ?? [];
2862
2863
        foreach ($resultSet as $key => &$result) {
2864
            // 数据转换为模型对象
2865
            $this->resultToModel($result, $this->options, true, $withRelationAttr);
2866
        }
2867
2868
        if (!empty($this->options['with'])) {
2869
            // 预载入
2870
            $result->eagerlyResultSet($resultSet, $this->options['with'], $withRelationAttr);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $result seems to be defined by a foreach iteration on line 2863. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
2871
        }
2872
2873
        if (!empty($this->options['with_join'])) {
2874
            // 预载入
2875
            $result->eagerlyResultSet($resultSet, $this->options['with_join'], $withRelationAttr, true);
2876
        }
2877
2878
        // 模型数据集转换
2879
        return $this->model->toCollection($resultSet, $collection ?? null);
2880
    }
2881
2882
    /**
2883
     * 处理数据集
2884
     * @access public
2885
     * @param array $resultSet 数据集
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2886
     * @return void
2887
     */
2888
    protected function resultSet(array &$resultSet): void
2889
    {
2890
        if (!empty($this->options['json'])) {
2891
            foreach ($resultSet as &$result) {
2892
                $this->jsonResult($result, $this->options['json'], true);
2893
            }
2894
        }
2895
2896
        if (!empty($this->options['with_attr'])) {
2897
            foreach ($resultSet as &$result) {
2898
                $this->getResultAttr($result, $this->options['with_attr']);
2899
            }
2900
        }
2901
2902
        if (!empty($this->options['visible']) || !empty($this->options['hidden'])) {
2903
            foreach ($resultSet as &$result) {
2904
                $this->filterResult($result);
2905
            }
2906
        }
2907
2908
        if (!empty($this->options['collection'])) {
2909
            // 返回Collection对象
2910
            $resultSet = new Collection($resultSet);
2911
        }
2912
    }
2913
2914
    /**
2915
     * 查找单条记录
2916
     * @access public
2917
     * @param mixed $data 查询数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2918
     * @return array|Model|null
2919
     * @throws DbException
2920
     * @throws ModelNotFoundException
2921
     * @throws DataNotFoundException
2922
     */
2923
    public function find($data = null)
2924
    {
2925
        if (!is_null($data)) {
2926
            // AR模式分析主键条件
2927
            $this->parsePkWhere($data);
2928
        }
2929
2930
        $result = $this->connection->find($this);
2931
2932
        // 数据处理
2933
        if (empty($result)) {
2934
            return $this->resultToEmpty();
2935
        }
2936
2937
        if (!empty($this->model) && empty($this->options['array'])) {
2938
            // 返回模型对象
2939
            $this->resultToModel($result, $this->options);
2940
        } else {
2941
            $this->result($result);
2942
        }
2943
2944
        return $result;
2945
    }
2946
2947
    /**
2948
     * 查找单条记录 不存在返回空数据(或者空模型)
2949
     * @access public
2950
     * @param mixed $data 数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2951
     * @return array|Model
2952
     */
2953
    public function findOrEmpty($data = null)
2954
    {
2955
        return $this->allowEmpty(true)->find($data);
2956
    }
2957
2958
    /**
2959
     * 处理空数据
2960
     * @access protected
2961
     * @return array|Model|null
2962
     * @throws DbException
2963
     * @throws ModelNotFoundException
2964
     * @throws DataNotFoundException
2965
     */
2966
    protected function resultToEmpty()
2967
    {
2968
        if (!empty($this->options['fail'])) {
2969
            $this->throwNotFound();
2970
        } elseif (!empty($this->options['allow_empty'])) {
2971
            return !empty($this->model) && empty($this->options['array']) ? $this->model->newInstance()->setQuery($this) : [];
2972
        } elseif (!empty($this->options['array'])) {
2973
            return [];
2974
        }
2975
    }
2976
2977
    /**
2978
     * 获取模型的更新条件
2979
     * @access protected
2980
     * @param array $options 查询参数
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2981
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
2982
    protected function getModelUpdateCondition(array $options)
2983
    {
2984
        return $options['where']['AND'] ?? null;
2985
    }
2986
2987
    /**
2988
     * 处理数据
2989
     * @access protected
2990
     * @param array $result 查询数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
2991
     * @return void
2992
     */
2993
    protected function result(array &$result): void
2994
    {
2995
        if (!empty($this->options['json'])) {
2996
            $this->jsonResult($result, $this->options['json'], true);
2997
        }
2998
2999
        if (!empty($this->options['with_attr'])) {
3000
            $this->getResultAttr($result, $this->options['with_attr']);
3001
        }
3002
3003
        $this->filterResult($result);
3004
    }
3005
3006
    /**
3007
     * 处理数据的可见和隐藏
3008
     * @access protected
3009
     * @param array $result 查询数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3010
     * @return void
3011
     */
3012
    protected function filterResult(&$result): void
3013
    {
3014
        if (!empty($this->options['visible'])) {
3015
            foreach ($this->options['visible'] as $key) {
3016
                $array[] = $key;
3017
            }
3018
            $result = array_intersect_key($result, array_flip($array));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $array seems to be defined by a foreach iteration on line 3015. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
3019
        } elseif (!empty($this->options['hidden'])) {
3020
            foreach ($this->options['hidden'] as $key) {
3021
                $array[] = $key;
3022
            }
3023
            $result = array_diff_key($result, array_flip($array));
3024
        }
3025
    }
3026
3027
    /**
3028
     * 使用获取器处理数据
3029
     * @access protected
3030
     * @param array $result   查询数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3031
     * @param array $withAttr 字段获取器
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3032
     * @return void
3033
     */
3034
    protected function getResultAttr(array &$result, array $withAttr = []): void
3035
    {
3036
        foreach ($withAttr as $name => $closure) {
3037
            $name = App::parseName($name);
3038
3039
            if (strpos($name, '.')) {
3040
                // 支持JSON字段 获取器定义
3041
                list($key, $field) = explode('.', $name);
3042
3043
                if (isset($result[$key])) {
3044
                    $result[$key][$field] = $closure($result[$key][$field] ?? null, $result[$key]);
3045
                }
3046
            } else {
3047
                $result[$name] = $closure($result[$name] ?? null, $result);
3048
            }
3049
        }
3050
    }
3051
3052
    /**
3053
     * JSON字段数据转换
3054
     * @access protected
3055
     * @param array $result           查询数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3056
     * @param array $json             JSON字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3057
     * @param bool  $assoc            是否转换为数组
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3058
     * @param array $withRelationAttr 关联获取器
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3059
     * @return void
3060
     */
3061
    protected function jsonResult(array &$result, array $json = [], bool $assoc = false, array $withRelationAttr = []): void
3062
    {
3063
        foreach ($json as $name) {
3064
            if (!isset($result[$name])) {
3065
                continue;
3066
            }
3067
3068
            $result[$name] = json_decode($result[$name], $assoc);
3069
3070
            if (!isset($withRelationAttr[$name])) {
3071
                continue;
3072
            }
3073
3074
            foreach ($withRelationAttr[$name] as $key => $closure) {
3075
                $data = get_object_vars($result[$name]);
3076
3077
                $result[$name]->$key = $closure($result[$name]->$key ?? null, $data);
3078
            }
3079
        }
3080
    }
3081
3082
    /**
3083
     * 查询数据转换为模型对象
3084
     * @access protected
3085
     * @param array $result           查询数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3086
     * @param array $options          查询参数
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3087
     * @param bool  $resultSet        是否为数据集查询
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3088
     * @param array $withRelationAttr 关联字段获取器
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3089
     * @return void
3090
     */
3091
    protected function resultToModel(array &$result, array $options = [], bool $resultSet = false, array $withRelationAttr = []): void
3092
    {
3093
        // 动态获取器
3094
        if (!empty($options['with_attr']) && empty($withRelationAttr)) {
3095
            foreach ($options['with_attr'] as $name => $val) {
3096
                if (strpos($name, '.')) {
3097
                    list($relation, $field) = explode('.', $name);
3098
3099
                    $withRelationAttr[$relation][$field] = $val;
3100
                    unset($options['with_attr'][$name]);
3101
                }
3102
            }
3103
        }
3104
3105
        // JSON 数据处理
3106
        if (!empty($options['json'])) {
3107
            $this->jsonResult($result, $options['json'], $options['json_assoc'], $withRelationAttr);
3108
        }
3109
3110
        $result = $this->model->newInstance($result, $resultSet ? null : $this->getModelUpdateCondition($options))->setQuery($this);
3111
3112
        // 动态获取器
3113
        if (!empty($options['with_attr'])) {
3114
            $result->withAttribute($options['with_attr']);
3115
        }
3116
3117
        // 输出属性控制
3118
        if (!empty($options['visible'])) {
3119
            $result->visible($options['visible']);
3120
        } elseif (!empty($options['hidden'])) {
3121
            $result->hidden($options['hidden']);
3122
        }
3123
3124
        if (!empty($options['append'])) {
3125
            $result->append($options['append']);
3126
        }
3127
3128
        // 关联查询
3129
        if (!empty($options['relation'])) {
3130
            $result->relationQuery($options['relation']);
3131
        }
3132
3133
        // 预载入查询
3134
        if (!$resultSet && !empty($options['with'])) {
3135
            $result->eagerlyResult($result, $options['with'], $withRelationAttr);
3136
        }
3137
3138
        // JOIN预载入查询
3139
        if (!$resultSet && !empty($options['with_join'])) {
3140
            $result->eagerlyResult($result, $options['with_join'], $withRelationAttr, true);
3141
        }
3142
3143
        // 关联统计
3144
        if (!empty($options['with_count'])) {
3145
            foreach ($options['with_count'] as $val) {
3146
                $result->relationCount($result, $val[0], $val[1], $val[2]);
3147
            }
3148
        }
3149
    }
3150
3151
    /**
3152
     * 查询失败 抛出异常
3153
     * @access protected
3154
     * @return void
3155
     * @throws ModelNotFoundException
3156
     * @throws DataNotFoundException
3157
     */
3158
    protected function throwNotFound(): void
3159
    {
3160
        if (!empty($this->model)) {
3161
            $class = get_class($this->model);
3162
            throw new ModelNotFoundException('model data Not Found:' . $class, $class, $this->options);
3163
        }
3164
3165
        $table = $this->getTable();
3166
        throw new DataNotFoundException('table data not Found:' . $table, $table, $this->options);
3167
    }
3168
3169
    /**
3170
     * 查找多条记录 如果不存在则抛出异常
3171
     * @access public
3172
     * @param array|string|Query|Closure $data 数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3173
     * @return array|PDOStatement|string|Model
3174
     * @throws DbException
3175
     * @throws ModelNotFoundException
3176
     * @throws DataNotFoundException
3177
     */
3178
    public function selectOrFail($data = null)
3179
    {
3180
        return $this->failException(true)->select($data);
3181
    }
3182
3183
    /**
3184
     * 查找单条记录 如果不存在则抛出异常
3185
     * @access public
3186
     * @param array|string|Query|Closure $data 数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3187
     * @return array|PDOStatement|string|Model
3188
     * @throws DbException
3189
     * @throws ModelNotFoundException
3190
     * @throws DataNotFoundException
3191
     */
3192
    public function findOrFail($data = null)
3193
    {
3194
        return $this->failException(true)->find($data);
3195
    }
3196
3197
    /**
3198
     * 分批数据返回处理
3199
     * @access public
3200
     * @param integer      $count    每次处理的数据数量
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3201
     * @param callable     $callback 处理回调方法
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3202
     * @param string|array $column   分批处理的字段名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3203
     * @param string       $order    字段排序
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3204
     * @return bool
3205
     * @throws DbException
3206
     */
3207
    public function chunk(int $count, callable $callback, $column = null, string $order = 'asc'): bool
3208
    {
3209
        $options = $this->getOptions();
3210
        $column  = $column ?: $this->getPk();
3211
3212
        if (isset($options['order'])) {
3213
            unset($options['order']);
3214
        }
3215
3216
        $bind = $this->bind;
3217
3218
        if (is_array($column)) {
3219
            $times = 1;
3220
            $query = $this->options($options)->page($times, $count);
3221
        } else {
3222
            $query = $this->options($options)->limit($count);
3223
3224
            if (strpos($column, '.')) {
3225
                list($alias, $key) = explode('.', $column);
3226
            } else {
3227
                $key = $column;
3228
            }
3229
        }
3230
3231
        $resultSet = $query->order($column, $order)->select();
3232
3233
        while (count($resultSet) > 0) {
3234
            if ($resultSet instanceof Collection) {
3235
                $resultSet = $resultSet->all();
3236
            }
3237
3238
            if (false === call_user_func($callback, $resultSet)) {
3239
                return false;
3240
            }
3241
3242
            if (isset($times)) {
3243
                $times++;
3244
                $query = $this->options($options)->page($times, $count);
3245
            } else {
3246
                $end    = end($resultSet);
3247
                $lastId = is_array($end) ? $end[$key] : $end->getData($key);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $key does not seem to be defined for all execution paths leading up to this point.
Loading history...
3248
3249
                $query = $this->options($options)
3250
                    ->limit($count)
3251
                    ->where($column, 'asc' == strtolower($order) ? '>' : '<', $lastId);
3252
            }
3253
3254
            $resultSet = $query->bind($bind)->order($column, $order)->select();
3255
        }
3256
3257
        return true;
3258
    }
3259
3260
    /**
3261
     * 获取绑定的参数 并清空
3262
     * @access public
3263
     * @param bool $clear 是否清空绑定数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3264
     * @return array
3265
     */
3266
    public function getBind(bool $clear = true): array
3267
    {
3268
        $bind = $this->bind;
3269
        if ($clear) {
3270
            $this->bind = [];
3271
        }
3272
3273
        return $bind;
3274
    }
3275
3276
    /**
3277
     * 创建子查询SQL
3278
     * @access public
3279
     * @param bool $sub 是否添加括号
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3280
     * @return string
3281
     * @throws DbException
3282
     */
3283
    public function buildSql(bool $sub = true): string
3284
    {
3285
        return $sub ? '( ' . $this->fetchSql()->select() . ' )' : $this->fetchSql()->select();
3286
    }
3287
3288
    /**
3289
     * 视图查询处理
3290
     * @access protected
3291
     * @param array $options 查询参数
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3292
     * @return void
3293
     */
3294
    protected function parseView(array &$options): void
3295
    {
3296
        foreach (['AND', 'OR'] as $logic) {
3297
            if (isset($options['where'][$logic])) {
3298
                foreach ($options['where'][$logic] as $key => $val) {
3299
                    if (array_key_exists($key, $options['map'])) {
3300
                        array_shift($val);
3301
                        array_unshift($val, $options['map'][$key]);
3302
                        $options['where'][$logic][$options['map'][$key]] = $val;
3303
                        unset($options['where'][$logic][$key]);
3304
                    }
3305
                }
3306
            }
3307
        }
3308
3309
        if (isset($options['order'])) {
3310
            // 视图查询排序处理
3311
            foreach ($options['order'] as $key => $val) {
3312
                if (is_numeric($key) && is_string($val)) {
3313
                    if (strpos($val, ' ')) {
3314
                        list($field, $sort) = explode(' ', $val);
3315
                        if (array_key_exists($field, $options['map'])) {
3316
                            $options['order'][$options['map'][$field]] = $sort;
3317
                            unset($options['order'][$key]);
3318
                        }
3319
                    } elseif (array_key_exists($val, $options['map'])) {
3320
                        $options['order'][$options['map'][$val]] = 'asc';
3321
                        unset($options['order'][$key]);
3322
                    }
3323
                } elseif (array_key_exists($key, $options['map'])) {
3324
                    $options['order'][$options['map'][$key]] = $val;
3325
                    unset($options['order'][$key]);
3326
                }
3327
            }
3328
        }
3329
    }
3330
3331
    /**
3332
     * 分析数据是否存在更新条件
3333
     * @access public
3334
     * @param array $data 数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3335
     * @return bool
3336
     * @throws Exception
3337
     */
3338
    public function parseUpdateData(&$data): bool
3339
    {
3340
        $pk       = $this->getPk();
3341
        $isUpdate = false;
3342
        // 如果存在主键数据 则自动作为更新条件
3343
        if (is_string($pk) && isset($data[$pk])) {
3344
            $this->where($pk, '=', $data[$pk]);
3345
            $this->options['key'] = $data[$pk];
3346
            unset($data[$pk]);
3347
            $isUpdate = true;
3348
        } elseif (is_array($pk)) {
3349
            // 增加复合主键支持
3350
            foreach ($pk as $field) {
3351
                if (isset($data[$field])) {
3352
                    $this->where($field, '=', $data[$field]);
3353
                    $isUpdate = true;
3354
                } else {
3355
                    // 如果缺少复合主键数据则不执行
3356
                    throw new Exception('miss complex primary data');
3357
                }
3358
                unset($data[$field]);
3359
            }
3360
        }
3361
3362
        return $isUpdate;
3363
    }
3364
3365
    /**
3366
     * 把主键值转换为查询条件 支持复合主键
3367
     * @access public
3368
     * @param array|string $data 主键数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
3369
     * @return void
3370
     * @throws Exception
3371
     */
3372
    public function parsePkWhere($data): void
3373
    {
3374
        $pk = $this->getPk();
3375
3376
        if (is_string($pk)) {
3377
            // 获取数据表
3378
            if (empty($this->options['table'])) {
3379
                $this->options['table'] = $this->getTable();
3380
            }
3381
3382
            $table = is_array($this->options['table']) ? key($this->options['table']) : $this->options['table'];
3383
3384
            if (!empty($this->options['alias'][$table])) {
3385
                $alias = $this->options['alias'][$table];
3386
            }
3387
3388
            $key = isset($alias) ? $alias . '.' . $pk : $pk;
3389
            // 根据主键查询
3390
            if (is_array($data)) {
3391
                $this->where($key, 'in', $data);
3392
            } else {
3393
                $this->where($key, '=', $data);
3394
                $this->options['key'] = $data;
3395
            }
3396
        }
3397
    }
3398
3399
    /**
3400
     * 分析表达式(可用于查询或者写入操作)
3401
     * @access public
3402
     * @return array
3403
     */
3404
    public function parseOptions(): array
3405
    {
3406
        $options = $this->getOptions();
3407
3408
        // 获取数据表
3409
        if (empty($options['table'])) {
3410
            $options['table'] = $this->getTable();
3411
        }
3412
3413
        if (!isset($options['where'])) {
3414
            $options['where'] = [];
3415
        } elseif (isset($options['view'])) {
3416
            // 视图查询条件处理
3417
            $this->parseView($options);
3418
        }
3419
3420
        if (!isset($options['field'])) {
3421
            $options['field'] = '*';
3422
        }
3423
3424
        foreach (['data', 'order', 'join', 'union'] as $name) {
3425
            if (!isset($options[$name])) {
3426
                $options[$name] = [];
3427
            }
3428
        }
3429
3430
        if (!isset($options['strict'])) {
3431
            $options['strict'] = $this->connection->getConfig('fields_strict');
3432
        }
3433
3434
        foreach (['master', 'lock', 'fetch_sql', 'array', 'distinct', 'procedure'] as $name) {
3435
            if (!isset($options[$name])) {
3436
                $options[$name] = false;
3437
            }
3438
        }
3439
3440
        foreach (['group', 'having', 'limit', 'force', 'comment', 'partition', 'duplicate', 'extra'] as $name) {
3441
            if (!isset($options[$name])) {
3442
                $options[$name] = '';
3443
            }
3444
        }
3445
3446
        if (isset($options['page'])) {
3447
            // 根据页数计算limit
3448
            list($page, $listRows) = $options['page'];
3449
            $page                  = $page > 0 ? $page : 1;
3450
            $listRows              = $listRows ? $listRows : (is_numeric($options['limit']) ? $options['limit'] : 20);
3451
            $offset                = $listRows * ($page - 1);
3452
            $options['limit']      = $offset . ',' . $listRows;
3453
        }
3454
3455
        $this->options = $options;
3456
3457
        return $options;
3458
    }
3459
3460
    public function __debugInfo()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __debugInfo()
Loading history...
3461
    {
3462
        return [
3463
            'name'    => $this->name,
3464
            'pk'      => $this->pk,
3465
            'prefix'  => $this->prefix,
3466
            'bind'    => $this->bind,
3467
            'options' => $this->options,
3468
        ];
3469
    }
3470
}
3471