为集合分页,Laravel
Paginate for a collection, Laravel
我尝试从 foreach 向每个用户添加一些新值,但因为我使用 get,现在我不能在响应中使用分页,但我还需要向每个用户添加该值。有什么想法吗?
public function statistics()
{
$users = User::select(['id', 'name'])->get();
foreach ($users as $key => $user) {
$history = AnswerHistory::where('user_id', '=', $user->id)->get();
$user->total_votes = count($history);
$user->total_time = gmdate("H:i:s", ($history->sum('answer_time')));
}
return response()->json($users);
}
根据您的 post,User
有很多 AnswerHistory
。你可以在他们之间建立关系。
因此 total_votes
和 total_time
通过 withCount
:
$users = User::withCount('answerHistories AS total_votes')
->withCount(['answerHistories AS total_time' => function($query) {
$query->select(DB::raw("SUM(answer_time)"));
}])->paginate(10);
并且可以通过getCollection
获取分页数据,修改里面的数据:
$users->getCollection()->transform(function ($data) {
$data->total_time = gmdate('H:i:s', $data->total_time);
return $data;
});
您可以自己创建分页,请查看此 Laravel 文档 https://laravel.com/docs/7.x/pagination#manually-creating-a-paginator。
我会建议使用 LengthAwarePaginator
这是数组
的一些代码示例
// creating pagination
$offset = max(0, ($page - 1) * $perPage);
$resultArray = array_slice($result, $offset, $perPage);
$paginator = new LengthAwarePaginator($resultArray, count($result), $perPage, $page);
$paginator->setPath(url()->current());
$paginator->appends(['per_page' => $perPage]);
return response()->json([
'message' => 'Success',
'data' => $paginator
]);
但我认为你的案例有更好的 "good" 解决方案,你可以加载 AnswerHistory
与 hasMany
Laravel 关系和 with
函数。
默认情况下 laravel 无法满足您的需求,但您可以做一些事情。
解决方法一可以先return分页器再修改集合
$users = User::select(['id', 'name'])->paginate(4)->toArray();
$users['data'] = array_map(function ($user) {
$history = AnswerHistory::where('user_id', '=', $user->id)->get();
$user->total_votes = count($history);
$user->total_time = gmdate("H:i:s", ($history->sum('answer_time')));
return $user;
}, $users['data']);
return $users;
解决方法二宏方式。如果您愿意,可以将 Collection 宏添加到服务提供者。这样你就可以在任何集合上调用 paginate() :
有关示例实施,请参阅 AppServiceProvider.php。
public function boot()
{
Collection::macro('paginate', function ($perPage, $total = null, $page = null, $pageName = 'page') {
$page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);
return new LengthAwarePaginator(
$this->forPage($page, $perPage),
$total ?: $this->count(),
$perPage,
$page,
[
'path' => LengthAwarePaginator::resolveCurrentPath(),
'pageName' => $pageName,
]
);
});
}
然后你的代码会像这样
$users = User::select(['id', 'name'])->get();
foreach ($users as $key => $user) {
$history = AnswerHistory::where('user_id', '=', $user->id)->get();
$user->total_votes = count($history);
$user->total_time = gmdate("H:i:s", ($history->sum('answer_time')));
}
return response()->json($users->paginate(4));
解决方法三子类方式。如果您想要一个不同于标准 Illuminate\Support\Collection
的 "pageable" 集合,请在您的应用程序中实现 Collection.php
的副本,并简单地替换您依赖项顶部的 use Illuminate\Support\Collection
语句use App\Support\Collection
:
的文件
<?php
namespace App\Support;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection as BaseCollection;
class Collection extends BaseCollection
{
public function paginate($perPage, $total = null, $page = null, $pageName = 'page')
{
$page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);
return new LengthAwarePaginator(
$this->forPage($page, $perPage),
$total ?: $this->count(),
$perPage,
$page,
[
'path' => LengthAwarePaginator::resolveCurrentPath(),
'pageName' => $pageName,
]
);
}
}
你的代码会像这样
// use Illuminate\Support\Collection
use App\Support\Collection;
$users = User::select(['id', 'name'])->get();
foreach ($users as $key => $user) {
$history = AnswerHistory::where('user_id', '=', $user->id)->get();
$user->total_votes = count($history);
$user->total_time = gmdate("H:i:s", ($history->sum('answer_time')));
}
return response()->json((new Collection($users))->paginate(4);
我尝试从 foreach 向每个用户添加一些新值,但因为我使用 get,现在我不能在响应中使用分页,但我还需要向每个用户添加该值。有什么想法吗?
public function statistics()
{
$users = User::select(['id', 'name'])->get();
foreach ($users as $key => $user) {
$history = AnswerHistory::where('user_id', '=', $user->id)->get();
$user->total_votes = count($history);
$user->total_time = gmdate("H:i:s", ($history->sum('answer_time')));
}
return response()->json($users);
}
根据您的 post,User
有很多 AnswerHistory
。你可以在他们之间建立关系。
因此 total_votes
和 total_time
通过 withCount
:
$users = User::withCount('answerHistories AS total_votes')
->withCount(['answerHistories AS total_time' => function($query) {
$query->select(DB::raw("SUM(answer_time)"));
}])->paginate(10);
并且可以通过getCollection
获取分页数据,修改里面的数据:
$users->getCollection()->transform(function ($data) {
$data->total_time = gmdate('H:i:s', $data->total_time);
return $data;
});
您可以自己创建分页,请查看此 Laravel 文档 https://laravel.com/docs/7.x/pagination#manually-creating-a-paginator。
我会建议使用 LengthAwarePaginator
这是数组
// creating pagination
$offset = max(0, ($page - 1) * $perPage);
$resultArray = array_slice($result, $offset, $perPage);
$paginator = new LengthAwarePaginator($resultArray, count($result), $perPage, $page);
$paginator->setPath(url()->current());
$paginator->appends(['per_page' => $perPage]);
return response()->json([
'message' => 'Success',
'data' => $paginator
]);
但我认为你的案例有更好的 "good" 解决方案,你可以加载 AnswerHistory
与 hasMany
Laravel 关系和 with
函数。
默认情况下 laravel 无法满足您的需求,但您可以做一些事情。
解决方法一可以先return分页器再修改集合
$users = User::select(['id', 'name'])->paginate(4)->toArray();
$users['data'] = array_map(function ($user) {
$history = AnswerHistory::where('user_id', '=', $user->id)->get();
$user->total_votes = count($history);
$user->total_time = gmdate("H:i:s", ($history->sum('answer_time')));
return $user;
}, $users['data']);
return $users;
解决方法二宏方式。如果您愿意,可以将 Collection 宏添加到服务提供者。这样你就可以在任何集合上调用 paginate() : 有关示例实施,请参阅 AppServiceProvider.php。
public function boot()
{
Collection::macro('paginate', function ($perPage, $total = null, $page = null, $pageName = 'page') {
$page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);
return new LengthAwarePaginator(
$this->forPage($page, $perPage),
$total ?: $this->count(),
$perPage,
$page,
[
'path' => LengthAwarePaginator::resolveCurrentPath(),
'pageName' => $pageName,
]
);
});
}
然后你的代码会像这样
$users = User::select(['id', 'name'])->get();
foreach ($users as $key => $user) {
$history = AnswerHistory::where('user_id', '=', $user->id)->get();
$user->total_votes = count($history);
$user->total_time = gmdate("H:i:s", ($history->sum('answer_time')));
}
return response()->json($users->paginate(4));
解决方法三子类方式。如果您想要一个不同于标准 Illuminate\Support\Collection
的 "pageable" 集合,请在您的应用程序中实现 Collection.php
的副本,并简单地替换您依赖项顶部的 use Illuminate\Support\Collection
语句use App\Support\Collection
:
<?php
namespace App\Support;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection as BaseCollection;
class Collection extends BaseCollection
{
public function paginate($perPage, $total = null, $page = null, $pageName = 'page')
{
$page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);
return new LengthAwarePaginator(
$this->forPage($page, $perPage),
$total ?: $this->count(),
$perPage,
$page,
[
'path' => LengthAwarePaginator::resolveCurrentPath(),
'pageName' => $pageName,
]
);
}
}
你的代码会像这样
// use Illuminate\Support\Collection
use App\Support\Collection;
$users = User::select(['id', 'name'])->get();
foreach ($users as $key => $user) {
$history = AnswerHistory::where('user_id', '=', $user->id)->get();
$user->total_votes = count($history);
$user->total_time = gmdate("H:i:s", ($history->sum('answer_time')));
}
return response()->json((new Collection($users))->paginate(4);