Laravel: 如何排序相关模型的结果?
Laravel: How to order results of related models?
我想出了以下查询生成器,我得到了准确的结果,除非我需要根据论坛的点赞总数和线程总数对结果进行排序并根据其进行分页。
下面是没有流行排序的查询生成器:
$limit = isset($_GET['limit']) && !empty($_GET['limit']) && is_numeric($_GET['limit']) ? (int) $_GET['limit'] : 10;
$page = isset($_GET['page']) && !empty($_GET['page']) && is_numeric($_GET['page']) ? (int) $_GET['page'] : 1;
$offset = ($page - 1) * $limit;
$forums = Forum::where('status', 1);
if(isset($_GET['search']) && !empty($_GET['search'])) {
$search = trim($_GET['search']);
$forums = $forums->where(function($query) use($search) {
$query->where('title', 'LIKE', '%' . $search . '%')->orWhere('content', 'LIKE', '%' . $search . '%');
});
}
if(isset($_GET['category']) && !empty($_GET['category'])) {
$forums = $forums->whereIn('category_id', explode(',', trim($_GET['category'])));
}
if(isset($_GET['sortby']) && !empty($_GET['sortby'])) {
$sortby = trim($_GET['sortby']);
if($sortby == 'newest') {
$forums = $forums->latest();
} elseif($sortby == 'oldest') {
$forums = $forums->oldest();
} elseif($sortby == 'popular') {
// Sort By: Popular | Logic: Total no of likes and threads to a forum
} else {
$forums = $forums->latest();
}
} else {
$forums = $forums->latest();
}
$forums = $forums->offset($offset)->limit($limit)->get();
我在论坛模型中定义了 eloquent 关系如下:
public function threads()
{
return $this->hasMany('App\ForumThread', 'forum_id', 'id');
}
public function likes()
{
return $this->hasMany('App\ForumLike', 'forum_id', 'id');
}
论坛 table 架构:
CREATE TABLE `forums` (
`id` bigint(20) UNSIGNED NOT NULL,
`category_id` int(10) UNSIGNED NOT NULL,
`user_id` bigint(20) UNSIGNED NOT NULL,
`title` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`content` longtext COLLATE utf8mb4_unicode_ci,
`image` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`tags` text COLLATE utf8mb4_unicode_ci,
`status` tinyint(3) UNSIGNED NOT NULL DEFAULT '1',
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`deleted_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
论坛喜欢 table 架构:
CREATE TABLE `forum_likes` (
`id` bigint(20) UNSIGNED NOT NULL,
`forum_id` bigint(20) UNSIGNED NOT NULL,
`user_id` bigint(20) UNSIGNED NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
论坛话题 table 架构如下:
CREATE TABLE `forum_threads` (
`id` bigint(20) UNSIGNED NOT NULL,
`forum_id` bigint(20) UNSIGNED NOT NULL,
`user_id` bigint(20) UNSIGNED NOT NULL,
`content` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`deleted_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
谢谢!
Counting Related
Models
If you want to count the number of results from a relationship without
actually loading them you may use the withCount method, which will
place a {relation}_count column on your resulting models.
因此,您可以使用 withCount()
,然后按放置的列对结果进行排序。例如 'likes' 关系:
} elseif ($sortby == 'popular') {
$forums = $forums->withCount('likes')->orderBy('likes_count', 'desc');
}
我想出了以下查询生成器,我得到了准确的结果,除非我需要根据论坛的点赞总数和线程总数对结果进行排序并根据其进行分页。
下面是没有流行排序的查询生成器:
$limit = isset($_GET['limit']) && !empty($_GET['limit']) && is_numeric($_GET['limit']) ? (int) $_GET['limit'] : 10;
$page = isset($_GET['page']) && !empty($_GET['page']) && is_numeric($_GET['page']) ? (int) $_GET['page'] : 1;
$offset = ($page - 1) * $limit;
$forums = Forum::where('status', 1);
if(isset($_GET['search']) && !empty($_GET['search'])) {
$search = trim($_GET['search']);
$forums = $forums->where(function($query) use($search) {
$query->where('title', 'LIKE', '%' . $search . '%')->orWhere('content', 'LIKE', '%' . $search . '%');
});
}
if(isset($_GET['category']) && !empty($_GET['category'])) {
$forums = $forums->whereIn('category_id', explode(',', trim($_GET['category'])));
}
if(isset($_GET['sortby']) && !empty($_GET['sortby'])) {
$sortby = trim($_GET['sortby']);
if($sortby == 'newest') {
$forums = $forums->latest();
} elseif($sortby == 'oldest') {
$forums = $forums->oldest();
} elseif($sortby == 'popular') {
// Sort By: Popular | Logic: Total no of likes and threads to a forum
} else {
$forums = $forums->latest();
}
} else {
$forums = $forums->latest();
}
$forums = $forums->offset($offset)->limit($limit)->get();
我在论坛模型中定义了 eloquent 关系如下:
public function threads()
{
return $this->hasMany('App\ForumThread', 'forum_id', 'id');
}
public function likes()
{
return $this->hasMany('App\ForumLike', 'forum_id', 'id');
}
论坛 table 架构:
CREATE TABLE `forums` (
`id` bigint(20) UNSIGNED NOT NULL,
`category_id` int(10) UNSIGNED NOT NULL,
`user_id` bigint(20) UNSIGNED NOT NULL,
`title` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`content` longtext COLLATE utf8mb4_unicode_ci,
`image` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`tags` text COLLATE utf8mb4_unicode_ci,
`status` tinyint(3) UNSIGNED NOT NULL DEFAULT '1',
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`deleted_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
论坛喜欢 table 架构:
CREATE TABLE `forum_likes` (
`id` bigint(20) UNSIGNED NOT NULL,
`forum_id` bigint(20) UNSIGNED NOT NULL,
`user_id` bigint(20) UNSIGNED NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
论坛话题 table 架构如下:
CREATE TABLE `forum_threads` (
`id` bigint(20) UNSIGNED NOT NULL,
`forum_id` bigint(20) UNSIGNED NOT NULL,
`user_id` bigint(20) UNSIGNED NOT NULL,
`content` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`deleted_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
谢谢!
Counting Related Models
If you want to count the number of results from a relationship without actually loading them you may use the withCount method, which will place a {relation}_count column on your resulting models.
因此,您可以使用 withCount()
,然后按放置的列对结果进行排序。例如 'likes' 关系:
} elseif ($sortby == 'popular') {
$forums = $forums->withCount('likes')->orderBy('likes_count', 'desc');
}