Completed
Push — 6.0 ( 4e9554...5f5e39 )
by liu
03:14
created

Query::getJoinTable()   B

Complexity

Conditions 11
Paths 16

Size

Total Lines 37
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 132

Importance

Changes 0
Metric Value
cc 11
eloc 21
nc 16
nop 2
dl 0
loc 37
ccs 0
cts 20
cp 0
crap 132
rs 7.3166
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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