Laravel 编码技巧 - 集合

作者: 温新

图书: 【Laravel 编码技巧】

阅读: 460

时间: 2024-09-08 00:14:39

使用自定义回调函数对集合进行 groupBy

如果您想按照数据库中不是直接列出的某些条件对结果进行分组,可以通过提供一个闭包函数来实现。

例如,如果您想按注册日期对用户进行分组,可以使用以下代码:

$users = User::all()->groupBy(function($item) {
    return $item->created_at->format('Y-m-d');
});

⚠️ 注意:这是在 Collection 类上执行的,因此是在从数据库获取结果之后进行的操作。

Laravel Scopes 可以使用“Higher Order”或Where方法进行组合。

以下是来自文档的示例。

在此之前:

User::popular()->orWhere(function (Builder $query) {
     $query->active();
})->get()

之后:

User::popular()->orWhere->active()->get();

多个集合方法连续使用

如果您使用->all()->get()查询所有结果,然后可以对相同的结果执行各种集合操作,而不会每次都查询数据库。

$users = User::all();
echo 'Max ID: ' . $users->max('id');
echo 'Average age: ' . $users->avg('age');
echo 'Total budget: ' . $users->sum('budget');

在分页情况下计算总和

当您只有分页的集合时,如何计算所有记录的总和?在分页之前进行计算,但使用相同的查询。

// 如何在分页的情况下获取 post_views 的总和?
$posts = Post::paginate(10);
// 这只会针对第一页,而不是所有的帖子
$sum = $posts->sum('post_views');

// 使用查询构建器实现
$query = Post::query();
// 计算总和
$sum = $query->sum('post_views');
// 然后从同一查询进行分页
$posts = $query->paginate(10);

foreach循环中使用分页的序列号

我们可以在分页中使用foreach集合项的索引作为序列号(SL)。

<!-- 在表头中添加序列号列 -->
<th>Serial</th>
<!-- 在foreach循环中使用序列号 -->
@foreach ($products as $product)
    <tr>
        <td>{{ $loop->index + $products->firstItem() }}</td>
        <!-- 其他列的内容 -->
        ...
    </tr>
@endforeach

通过在循环中使用 $loop->index + $products->firstItem(),您可以在分页中正确计算序列号,解决了在下一页(例如,?page=2&...)中索引计数连续的问题。

高阶集合信息

集合还支持“higher order messages”(高阶消息),这是对集合执行常见操作的快捷方式。以下示例计算了在一份优惠中每组产品的价格总和。

$offer = [
    'name'  => 'offer1',
    'lines' => [
        ['group' => 1, 'price' => 10],
        ['group' => 1, 'price' => 20],
        ['group' => 2, 'price' => 30],
        ['group' => 2, 'price' => 40],
        ['group' => 3, 'price' => 50],
        ['group' => 3, 'price' => 60]
    ]
];

$totalPerGroup = collect($offer['lines'])->groupBy->group->map->sum('price');

获取一个现有的键,如果不存在,则插入一个值并返回该值

在 Laravel 8.81 中,引入了 getOrPut 方法到集合(Collections),简化了一种情况,即您要么获取现有的键,要么在键不存在时插入一个值并返回该值。

$key = 'name';

// 仍然有效的方式
if ($this->collection->has($key) === false) {
    $this->collection->put($key, ...);
}

return $this->collection->get($key);

// 使用 `getOrPut()` 方法与闭包
return $this->collection->getOrPut($key, fn() => ...);

// 或传递一个固定的值
return $this->collection->getOrPut($key, $value='teacoders');

静态时间法

times 方法是集合(Collection)类的静态方法,通过调用指定次数的闭包来创建一个新的集合。

Collection::times(7, function ($number) {
    return now()->addDays($number)->format('d-m-Y');
});
// 输出:[01-04-2022, 02-04-2022, ..., 07-04-2022]
请登录后再评论