思考并回答以下问题:
- 集合是“macroable”的,怎么理解?
- new static是什么意思?
- get_class()函数是什么意思?
简介
Illuminate\Support\Collection类为处理数组数据提供了流式、方便的封装。例如,查看下面的代码,我们使用辅助函数collect创建一个新的集合实例,为每一个元素运行strtoupper函数,然后移除所有空元素:
1 | $collection = collect(['taylor', 'abigail', null])->map(function ($name) { |
正如你所看到的,Collection类允许你使用方法链对底层数组执行匹配和移除操作,通常,每个Collection方法都会返回一个新的Collection实例。
创建集合
正如上面所提到的,辅助函数collect为给定数组返回一个新的Illuminate\Support\Collection实例,所以,创建集合很简单:1
$collection = collect([1, 2, 3]);
注:默认情况下,Eloquent查询的结果总是返回Collection实例。
扩展集合
集合是“macroable”的,这意味着我们可以在运行时动态添加方法到Collection类,例如,下面的代码添加了toUpper方法到Collection类:1
2
3
4
5
6
7
8
9
10
11
12
13use Illuminate\Support\Str;
Collection::macro('toUpper', function () {
return $this->map(function ($value) {
return Str::upper($value);
});
});
$collection = collect(['first', 'second']);
$upper = $collection->toUpper();
// ['FIRST', 'SECOND']
通常,我们需要在服务提供者中声明集合宏。
懒集合
简介
为了继续完善功能已经很强大的Collection类,LazyCollection类使用了PHP的生成器,从而可以通过极低的内存处理极大的数据集。
例如,假设你的应用需要通过Laravel提供的集合方法来解析并处理几个GB大小的日志文件,这个时候就可以使用懒集合(LazyCollection),它不会一次性将整个文件读入内存,而是每次只读取文件的一小部分:1
2
3
4
5
6
7
8
9
10
11
12
13
14use App\LogEntry;
use Illuminate\Support\LazyCollection;
LazyCollection::make(function () {
$handle = fopen('log.txt', 'r');
while (($line = fgets($handle)) !== false) {
yield $line;
}
})->chunk(4)->map(function ($lines) {
return LogEntry::fromLines($lines);
})->each(function (LogEntry $logEntry) {
// Process the log entry...
});
或者,假设你需要迭代10000个Eloquent模型实例,使用传统的Laravel集合,所有10000个Eloquent模型实例必须一次性加载到内存中:
1 | $users = App\User::all()->filter(function ($user) { |
而现在,查询构建器的cursor方法会返回一个LazyCollection实例,这样一来,我们仍然只需对数据库做一次查询,但是一次只会加载一个Eloquent模型实例到内存。在这个例子中,filter回调只有在迭代到每个独立用户时才会执行,从而大幅降低对内存的占用:1
2
3
4
5
6
7$users = App\User::cursor()->filter(function ($user) {
return $user->id > 500;
});
foreach ($users as $user) {
echo $user->id;
}
创建懒集合
要创建一个懒集合实例,需要传递一个PHP生成器函数到集合的make方法:1
2
3
4
5
6
7
8
9use Illuminate\Support\LazyCollection;
LazyCollection::make(function () {
$handle = fopen('log.txt', 'r');
while (($line = fgets($handle)) !== false) {
yield $line;
}
});
new static
无论是new static()还是new self()都是new一个对象,这两个方法new出来的对象有什么区别呢?说白了就是new出来的到底是同一个类的实例还是不同类的实例。
为了探究上面的问题,我们先上一段简单的代码。
1 | class Father |
这里无论是getNewFather还是getNewCaller都是返回的Father这个实例,到这里貌似new self()还是new static()是没有区别的,我们接着走。1
2
3
4
5
6
7
8
9class Sun1 extends Father
{
}
$sun1 = new Sun1();
var_dump($sun1->getNewFather()); // object(Father)#4 (0) { }
var_dump($sun1->getNewCaller()); // object(Sun1)#4 (0) { }
这里我们发现了getNewFather返回的是Father的实例,而getNewCaller返回的是调用者的实例。
他们的区别只有在继承中才能体现出来、如果没有任何继承、那么二者没有任何区别。
然后new self()返回的实例是不会变的,无论谁去调用,都返回的一个类的实例,而new static则是由调用者决定的。
LazyCollection
Illuminate\Support\LazyCollection.php
1 | namespace Illuminate\Support; |