Passed
Pull Request — 5.1 (#1748)
by guanguans
09:27
created

Collection::jsonSerialize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
// +----------------------------------------------------------------------
1 ignored issue
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: zhangyajun <[email protected]>
10
// +----------------------------------------------------------------------
11
12
namespace think;
13
14
use ArrayAccess;
15
use ArrayIterator;
16
use Countable;
17
use IteratorAggregate;
18
use JsonSerializable;
19
20
class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable
1 ignored issue
show
Coding Style introduced by
Missing class doc comment
Loading history...
21
{
22
    /**
23
     * 数据集数据
24
     * @var array
25
     */
26
    protected $items = [];
27
28
    public function __construct($items = [])
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
29
    {
30
        $this->items = $this->convertToArray($items);
31
    }
32
33
    public static function make($items = [])
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
34
    {
35
        return new static($items);
36
    }
37
38
    /**
39
     * 是否为空
40
     * @access public
41
     * @return bool
42
     */
43
    public function isEmpty()
44
    {
45
        return empty($this->items);
46
    }
47
48
    public function toArray()
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
49
    {
50
        return array_map(function ($value) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
51
            return ($value instanceof Model || $value instanceof self) ? $value->toArray() : $value;
52
        }, $this->items);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
53
    }
54
55
    public function all()
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
56
    {
57
        return $this->items;
58
    }
59
60
    /**
61
     * 合并数组
62
     *
63
     * @access public
64
     * @param  mixed $items
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
65
     * @return static
66
     */
67
    public function merge($items)
68
    {
69
        return new static(array_merge($this->items, $this->convertToArray($items)));
70
    }
71
72
    /**
73
     * 交换数组中的键和值
74
     *
75
     * @access public
76
     * @return static
77
     */
78
    public function flip()
79
    {
80
        return new static(array_flip($this->items));
81
    }
82
83
    /**
84
     * 按指定键整理数据
85
     *
86
     * @access public
87
     * @param  mixed    $items      数据
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 6 found
Loading history...
88
     * @param  string   $indexKey   键名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 3 found
Loading history...
89
     * @return array
90
     */
91
    public function dictionary($items = null, &$indexKey = null)
92
    {
93
        if ($items instanceof self || $items instanceof Paginator) {
94
            $items = $items->all();
0 ignored issues
show
Bug introduced by
The method all() does not exist on think\Paginator. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

94
            /** @scrutinizer ignore-call */ 
95
            $items = $items->all();
Loading history...
95
        }
96
97
        $items = is_null($items) ? $this->items : $items;
98
99
        if ($items && empty($indexKey)) {
100
            $indexKey = is_array($items[0]) ? 'id' : $items[0]->getPk();
101
        }
102
103
        if (isset($indexKey) && is_string($indexKey)) {
104
            return array_column($items, null, $indexKey);
0 ignored issues
show
Bug introduced by
It seems like $items can also be of type think\Collection and think\Paginator; however, parameter $input of array_column() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

104
            return array_column(/** @scrutinizer ignore-type */ $items, null, $indexKey);
Loading history...
105
        }
106
107
        return $items;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $items also could return the type think\Collection|think\Paginator which is incompatible with the documented return type array.
Loading history...
108
    }
109
110
    /**
111
     * 比较数组,返回差集
112
     *
113
     * @access public
114
     * @param  mixed    $items      数据
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 6 found
Loading history...
115
     * @param  string   $indexKey   指定比较的键名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 3 found
Loading history...
116
     * @return static
117
     */
118
    public function diff($items, $indexKey = null)
119
    {
120
        if ($this->isEmpty() || is_scalar($this->items[0])) {
121
            return new static(array_diff($this->items, $this->convertToArray($items)));
122
        }
123
124
        $diff       = [];
125
        $dictionary = $this->dictionary($items, $indexKey);
126
127
        if (is_string($indexKey)) {
128
            foreach ($this->items as $item) {
129
                if (!isset($dictionary[$item[$indexKey]])) {
130
                    $diff[] = $item;
131
                }
132
            }
133
        }
134
135
        return new static($diff);
136
    }
137
138
    /**
139
     * 比较数组,返回交集
140
     *
141
     * @access public
142
     * @param  mixed    $items      数据
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 6 found
Loading history...
143
     * @param  string   $indexKey   指定比较的键名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 3 found
Loading history...
144
     * @return static
145
     */
146
    public function intersect($items, $indexKey = null)
147
    {
148
        if ($this->isEmpty() || is_scalar($this->items[0])) {
149
            return new static(array_diff($this->items, $this->convertToArray($items)));
150
        }
151
152
        $intersect  = [];
153
        $dictionary = $this->dictionary($items, $indexKey);
154
155
        if (is_string($indexKey)) {
156
            foreach ($this->items as $item) {
157
                if (isset($dictionary[$item[$indexKey]])) {
158
                    $intersect[] = $item;
159
                }
160
            }
161
        }
162
163
        return new static($intersect);
164
    }
165
166
    /**
167
     * 返回数组中所有的键名
168
     *
169
     * @access public
170
     * @return array
171
     */
172
    public function keys()
173
    {
174
        $current = current($this->items);
175
176
        if (is_scalar($current)) {
177
            $array = $this->items;
178
        } elseif (is_array($current)) {
179
            $array = $current;
180
        } else {
181
            $array = $current->toArray();
182
        }
183
184
        return array_keys($array);
185
    }
186
187
    /**
188
     * 删除数组的最后一个元素(出栈)
189
     *
190
     * @access public
191
     * @return mixed
192
     */
193
    public function pop()
194
    {
195
        return array_pop($this->items);
196
    }
197
198
    /**
199
     * 通过使用用户自定义函数,以字符串返回数组
200
     *
201
     * @access public
202
     * @param  callable $callback
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
203
     * @param  mixed    $initial
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
204
     * @return mixed
205
     */
206
    public function reduce(callable $callback, $initial = null)
207
    {
208
        return array_reduce($this->items, $callback, $initial);
209
    }
210
211
    /**
212
     * 以相反的顺序返回数组。
213
     *
214
     * @access public
215
     * @return static
216
     */
217
    public function reverse()
218
    {
219
        return new static(array_reverse($this->items));
220
    }
221
222
    /**
223
     * 删除数组中首个元素,并返回被删除元素的值
224
     *
225
     * @access public
226
     * @return mixed
227
     */
228
    public function shift()
229
    {
230
        return array_shift($this->items);
231
    }
232
233
    /**
234
     * 在数组结尾插入一个元素
235
     * @access public
236
     * @param  mixed  $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
237
     * @param  mixed  $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
238
     * @return void
239
     */
240
    public function push($value, $key = null)
241
    {
242
        if (is_null($key)) {
243
            $this->items[] = $value;
244
        } else {
245
            $this->items[$key] = $value;
246
        }
247
    }
248
249
    /**
250
     * 把一个数组分割为新的数组块.
251
     *
252
     * @access public
253
     * @param  int  $size
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
254
     * @param  bool $preserveKeys
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
255
     * @return static
256
     */
257
    public function chunk($size, $preserveKeys = false)
258
    {
259
        $chunks = [];
260
261
        foreach (array_chunk($this->items, $size, $preserveKeys) as $chunk) {
262
            $chunks[] = new static($chunk);
263
        }
264
265
        return new static($chunks);
266
    }
267
268
    /**
269
     * 在数组开头插入一个元素
270
     * @access public
271
     * @param mixed  $value
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
272
     * @param mixed  $key
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
273
     * @return void
274
     */
275
    public function unshift($value, $key = null)
276
    {
277
        if (is_null($key)) {
278
            array_unshift($this->items, $value);
279
        } else {
280
            $this->items = [$key => $value] + $this->items;
281
        }
282
    }
283
284
    /**
285
     * 给每个元素执行个回调
286
     *
287
     * @access public
288
     * @param  callable $callback
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
289
     * @return $this
290
     */
291
    public function each(callable $callback)
292
    {
293
        foreach ($this->items as $key => $item) {
294
            $result = $callback($item, $key);
295
296
            if (false === $result) {
297
                break;
298
            } elseif (!is_object($item)) {
299
                $this->items[$key] = $result;
300
            }
301
        }
302
303
        return $this;
304
    }
305
306
    /**
307
     * 用回调函数处理数组中的元素
308
     * @access public
309
     * @param  callable|null $callback
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
310
     * @return static
311
     */
312
    public function map(callable $callback)
313
    {
314
        return new static(array_map($callback, $this->items));
315
    }
316
317
    /**
318
     * 用回调函数过滤数组中的元素
319
     * @access public
320
     * @param  callable|null $callback
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
321
     * @return static
322
     */
323
    public function filter(callable $callback = null)
324
    {
325
        if ($callback) {
326
            return new static(array_filter($this->items, $callback));
327
        }
328
329
        return new static(array_filter($this->items));
330
    }
331
332
    /**
333
     * 根据字段条件过滤数组中的元素
334
     * @access public
335
     * @param  string   $field 字段名
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
336
     * @param  mixed    $operator 操作符
337
     * @param  mixed    $value 数据
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
338
     * @return static
339
     */
340
    public function where($field, $operator, $value = null)
341
    {
342
        if (is_null($value)) {
343
            $value    = $operator;
344
            $operator = '=';
345
        }
346
347
        return $this->filter(function ($data) use ($field, $operator, $value) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
348
            if (strpos($field, '.')) {
349
                list($field, $relation) = explode('.', $field);
350
351
                $result = isset($data[$field][$relation]) ? $data[$field][$relation] : null;
352
            } else {
353
                $result = isset($data[$field]) ? $data[$field] : null;
354
            }
355
356
            switch ($operator) {
357
                case '===':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
358
                    return $result === $value;
359
                case '!==':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
360
                    return $result !== $value;
361
                case '!=':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
362
                case '<>':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
363
                    return $result != $value;
364
                case '>':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
365
                    return $result > $value;
366
                case '>=':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
367
                    return $result >= $value;
368
                case '<':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
369
                    return $result < $value;
370
                case '<=':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
371
                    return $result <= $value;
372
                case 'like':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
373
                    return is_string($result) && false !== strpos($result, $value);
374
                case 'not like':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
375
                    return is_string($result) && false === strpos($result, $value);
376
                case 'in':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
377
                    return is_scalar($result) && in_array($result, $value, true);
378
                case 'not in':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
379
                    return is_scalar($result) && !in_array($result, $value, true);
380
                case 'between':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
381
                    list($min, $max) = is_string($value) ? explode(',', $value) : $value;
382
                    return is_scalar($result) && $result >= $min && $result <= $max;
383
                case 'not between':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
384
                    list($min, $max) = is_string($value) ? explode(',', $value) : $value;
385
                    return is_scalar($result) && $result > $max || $result < $min;
386
                case '==':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
387
                case '=':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
388
                default:
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
389
                    return $result == $value;
390
            }
391
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
392
    }
393
394
    /**
395
     * 返回数据中指定的一列
396
     * @access public
397
     * @param mixed $columnKey 键名
1 ignored issue
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
398
     * @param mixed $indexKey  作为索引值的列
1 ignored issue
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
399
     * @return array
400
     */
401
    public function column($columnKey, $indexKey = null)
402
    {
403
        return array_column($this->items, $columnKey, $indexKey);
404
    }
405
406
    /**
407
     * 对数组排序
408
     *
409
     * @access public
410
     * @param  callable|null $callback
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
411
     * @return static
412
     */
413
    public function sort(callable $callback = null)
414
    {
415
        $items = $this->items;
416
417
        $callback = $callback ?: function ($a, $b) {
418
            return $a == $b ? 0 : (($a < $b) ? -1 : 1);
419
420
        };
421
422
        uasort($items, $callback);
423
424
        return new static($items);
425
    }
426
427
    /**
428
     * 指定字段排序
429
     * @access public
430
     * @param  string       $field 排序字段
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
431
     * @param  string       $order 排序
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
432
     * @param  bool         $intSort 是否为数字排序
433
     * @return $this
434
     */
435
    public function order($field, $order = null, $intSort = true)
436
    {
437
        return $this->sort(function ($a, $b) use ($field, $order, $intSort) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
438
            $fieldA = isset($a[$field]) ? $a[$field] : null;
439
            $fieldB = isset($b[$field]) ? $b[$field] : null;
440
441
            if ($intSort) {
442
                return 'desc' == strtolower($order) ? $fieldB >= $fieldA : $fieldA >= $fieldB;
443
            } else {
444
                return 'desc' == strtolower($order) ? strcmp($fieldB, $fieldA) : strcmp($fieldA, $fieldB);
445
            }
446
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
447
    }
448
449
    /**
450
     * 将数组打乱
451
     *
452
     * @access public
453
     * @return static
454
     */
455
    public function shuffle()
456
    {
457
        $items = $this->items;
458
459
        shuffle($items);
460
461
        return new static($items);
462
    }
463
464
    /**
465
     * 截取数组
466
     *
467
     * @access public
468
     * @param  int  $offset
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
469
     * @param  int  $length
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
470
     * @param  bool $preserveKeys
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
471
     * @return static
472
     */
473
    public function slice($offset, $length = null, $preserveKeys = false)
474
    {
475
        return new static(array_slice($this->items, $offset, $length, $preserveKeys));
476
    }
477
478
    // ArrayAccess
479
    public function offsetExists($offset)
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
480
    {
481
        return array_key_exists($offset, $this->items);
482
    }
483
484
    public function offsetGet($offset)
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
485
    {
486
        return $this->items[$offset];
487
    }
488
489
    public function offsetSet($offset, $value)
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
490
    {
491
        if (is_null($offset)) {
492
            $this->items[] = $value;
493
        } else {
494
            $this->items[$offset] = $value;
495
        }
496
    }
497
498
    public function offsetUnset($offset)
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
499
    {
500
        unset($this->items[$offset]);
501
    }
502
503
    //Countable
504
    public function count()
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
505
    {
506
        return count($this->items);
507
    }
508
509
    //IteratorAggregate
510
    public function getIterator()
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
511
    {
512
        return new ArrayIterator($this->items);
513
    }
514
515
    //JsonSerializable
516
    public function jsonSerialize()
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
517
    {
518
        return $this->toArray();
519
    }
520
521
    /**
522
     * 转换当前数据集为JSON字符串
523
     * @access public
524
     * @param  integer $options json参数
525
     * @return string
526
     */
527
    public function toJson($options = JSON_UNESCAPED_UNICODE)
528
    {
529
        return json_encode($this->toArray(), $options);
530
    }
531
532
    public function __toString()
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
533
    {
534
        return $this->toJson();
535
    }
536
537
    /**
538
     * 转换成数组
539
     *
540
     * @access public
541
     * @param  mixed $items
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
542
     * @return array
543
     */
544
    protected function convertToArray($items)
545
    {
546
        if ($items instanceof self) {
547
            return $items->all();
548
        }
549
550
        return (array) $items;
551
    }
552
}
553