[英]Eloquent ORM pagination Reddit-like - before/after hash-id
我有一個排名列的帖子表。 有沒有辦法從一個帖子的ID開始檢索前20個帖子,同時按排名排序。 它的行為與reddit的分頁相似。
防爆。 domain.com/posts/previous/{id_of_post_to_start_from}
UPDATE
讓我重新說一下。 正常的laravel / eloquent(簡單)分頁將使用頁面,可以通過執行以下操作來實現:
$posts = Post::with(array('user'=>function($q){
$q->select('id', 'img','nick', 'points', 'slug');
}))
->with('categories')
->with('voted')
->orderBy('rank', 'DESC')
->orderBy('created_at','DESC')
->simplePaginate(20);
return view('layouts.home')->with('posts',$posts);
這將使用帶有?page=pageNo
參數的url。 因為排名變化非常快,我真正想要的是能夠在id或hashId標識的某個帖子之后獲得以下或之前的帖子。 這是reddit的方式:
https://www.reddit.com/?count=25&after=t3_4g1n0n
更新2
@jarek的答案似乎在按排名欄排序時起作用,因為它很少或沒有重復,但在按投票數排序時失敗。 它只顯示3頁而不是5頁,在最后一頁中會跳過一些行。 我一直試圖解決這個問題一整天,我真的不知道下一步該去哪里。 請幫忙。
我的網址是/ordered-by-votes?before=hashId
和/ordered-by-votes?after=hashId
按結構votes desc, created_at desc
排序的表結構:
| id | rank | votes | url | created_at |
+-----+-----------------------------+-----+------------+---------------------+
| 41 | 220.6454978 | 16 | 7X1dqLLNRG | 2016-04-24 08:02:03 |
| 32 | 192.6005579 | 15 | k39djkOGP0 | 2016-04-09 17:49:22 |
| 81 | 401.8382322 | 13 | 7X1dqPLNRG | 2016-07-27 18:04:14 |
| 36 | 192.6460924 | 12 | mZEzDLzxpb | 2016-04-09 19:36:12 |
| 35 | 192.5188647 | 9 | 5ykOxjNBp7 | 2016-04-09 19:34:29 |
| 50 | 325.8341567 | 8 | lm2dpyxOQY | 2016-06-18 06:39:19 |
| 34 | 192.4059869 | 7 | EDMOM0d16m | 2016-04-09 19:31:41 |
| 33 | 192.2031068 | 6 | J6RN0mdGmY | 2016-04-09 17:49:44 |
| 57 | 325.5080990 | 3 | 76mz7R1OGl | 2016-06-18 07:54:15 |
| 56 | 325.5039213 | 3 | KE0NQEkN1p | 2016-06-18 07:51:07 |
| 40 | 193.2540546 | 3 | 796Na28dJr | 2016-04-10 10:43:43 |
| 39 | 193.2262101 | 3 | 6yMNr0Ox-Y | 2016-04-10 10:22:50 |
| 38 | 193.2205435 | 3 | Y21OmeODEp | 2016-04-10 10:18:35 |
| 55 | 325.3238522 | 2 | e4Bd3xoOjg | 2016-06-18 07:48:08 |
| 54 | 325.3145633 | 2 | Z56zRyqOYM | 2016-06-18 07:41:10 |
| 53 | 325.2995633 | 2 | G3JdEMGd0y | 2016-06-18 07:29:55 |
| 52 | 325.2952967 | 2 | gm8dna7Noq | 2016-06-18 07:26:43 |
| 49 | 323.1741856 | 2 | -41zKQndp3 | 2016-06-17 04:55:53 |
| 48 | 323.1371411 | 2 | obmd2DLze2 | 2016-06-17 04:28:06 |
| 47 | 322.2090522 | 2 | 2KGdGR-N9j | 2016-06-16 16:52:02 |
| 45 | 318.4326967 | 2 | ngYN4lRNDB | 2016-06-14 17:39:46 |
| 42 | 244.7367189 | 2 | -arOeX3dby | 2016-05-07 08:27:47 |
| 27 | 191.1572300 | 2 | 7rbzy5zXGm | 2016-04-09 10:43:10 |
| 20 | 183.1333856 | 2 | PE4N13Oa-r | 2016-04-05 06:25:17 |
| 102 | 430.7966222 | 1 | -arOe3mNby | 2016-08-12 09:58:29 |
| 93 | 415.2774667 | 1 | G3JdEjGO0y | 2016-08-04 07:59:07 |
| 80 | 397.8948667 | 1 | 796NaX8zJr | 2016-07-26 06:42:10 |
| 79 | 397.0725111 | 1 | 6yMNrm0zx- | 2016-07-25 20:25:24 |
| 77 | 397.0368667 | 1 | j3-Ob8aN9k | 2016-07-25 19:58:40 |
| 75 | 388.2400889 | 1 | 5ykOxQjzBp | 2016-07-21 06:01:05 |
| 72 | 386.3236889 | 1 | k39djBkdGP | 2016-07-20 06:03:47 |
| 65 | 378.7166889 | 1 | B0kd5bkO7L | 2016-07-16 06:58:32 |
| 64 | 367.0564222 | 1 | l16zlkxOqe | 2016-07-10 05:13:20 |
| 63 | 365.7214000 | 1 | qBEdkk2d2M | 2016-07-09 12:32:04 |
| 62 | 354.0362889 | 1 | Xk3O-1jOEY | 2016-07-03 10:28:14 |
| 61 | 354.0347556 | 1 | kryNP1Kd9a | 2016-07-03 10:27:05 |
| 60 | 353.5897333 | 1 | PE4N123da- | 2016-07-03 04:53:19 |
| 58 | 329.7797111 | 1 | J-azJQ2Oeb | 2016-06-20 19:15:48 |
| 44 | 257.9238889 | 1 | jexdZ0JzR5 | 2016-05-14 09:03:56 |
| 59 | 350.6545778 | 0 | QK2N6yKzn6 | 2016-07-01 16:11:57 |
| 51 | 324.9408000 | 0 | 2P8O8P-Opm | 2016-06-18 06:46:37 |
| 46 | 321.4635111 | 0 | Da8zBj6z-Y | 2016-06-16 11:18:39 |
| 43 | 249.2581556 | 0 | e6XOLJENQ3 | 2016-05-09 20:44:38 |
| 92 | 413.8514933 | -26 | gm8dn07zoq | 2016-08-04 07:50:52 |
模型中的after
方法
public function scopeAfter($query, self $post)
{
return $query->orderBy('votes', 'desc')
->latest()
->where('status', '=', 'approved')
->where('id', '<>', $post->id)
->where('votes', '<=', $post->votes)
->where('created_at', '<=', $post->created_at);
}
控制器:
$posts=null;
if(isset($req['before'])){
//...
} elseif (isset($req['after'])){
$prevPost = Post::where('url','=',$req['after'])->first();
$posts= Post::after($prevPost)
->with('categories', 'voted')
->with(array('user'=>function($q){
$q->select('id', 'img','nick', 'points', 'slug');
}))
->limit(10)
->get();
} else {
// if no params, get the first 10
$posts= Post::with('categories', 'voted')
->with(array('user'=>function($q){
$q->select('id', 'img','nick', 'points', 'slug');
}))
->where('status','=','approved')
->orderBy('votes', 'desc')
->orderBy('created_at', 'desc')
->limit(10)
->get();
}
//return $posts;
視圖鏈接
<a href="{{url('/ordered-by-votes') . '?' . http_build_query(['after' => $lastPost->url])}}" class="btn after">< Previous</a>
<a href="{{url('/ordered-by-votes') . '?' . http_build_query(['before' => $firstPost->url])}}" class="btn before">Before ></a>
更新3
應該有5頁,44個結果,但只顯示3頁和27個結果。
第1頁 - 正確 - 10個結果
from 7X1dqLLNRG to KE0NQEkN1p
第2頁 - 正確 - 10個結果
from 796Na28dJr to 2KGdGR-N9j
第3頁 - 不正確 - 只有7個結果以錯誤的順序顯示
ngYN4lRNDB (OK)
-arOeX3dby (OK)
7rbzy5zXGm (OK)
PE4N13Oa-r (OK)
jexdZ0JzR5 (NOT OK)
Da8zBj6z-Y (NOT OK)
e6XOLJENQ3 (NOT OK)
以下是您使用代碼的方法:
// controller
$post = Post::findByWhateverYouWant($key_from_route);
// higher ranked:
$paginator = Post::before($post)
->with('categories', 'votes')
->simplePaginate(20);
// you need to reverse this result in order to sort
// appropriately but AFTER the query was executed
return $paginator->setCollection($paginator->reverse());
// lower ranked:
return Post::after($post)
->with('categories', 'votes')
->simplePaginate(20);
這里是提到范圍的模型:
public function scopeBefore($query, self $post, $sortBy = 'votes')
{
return $query->orderBy($sortBy)
->orderBy('created_at')
->where('id', '<>', $post->id)
->where(function ($q) use ($post, $sortBy) {
$q->where($sortBy, '=', $post->{$sortBy})
->where('created_at', '>=', $post->created_at)
->orWhere($sortBy, '>', $post->{$sortBy});
});
}
public function scopeAfter($query, self $post, $sortBy = 'votes')
{
return $query->orderBy($sortBy, 'desc')
->latest()
->where('id', '<>', $post->id)
->where(function ($q) use ($post, $sortBy) {
$q->where($sortBy, '=', $post->{$sortBy})
->where('created_at', '<=', $post->created_at)
->orWhere($sortBy, '<', $post->{$sortBy});
});
}
您可以向這些范圍添加第3個參數,以便根據需要進行
2nd column
自定義。
使用這樣的東西(你沒有共享任何代碼,所以把你的模型和變量放在這里):
$perPage = 20;
$toSkip = $id_of_post_to_start_from - $perPage;
$toSkip = $toSkip < 0 ? 0 : $toSkip;
$prevousTwentyPosts = Post::orderBy('rank', 'desc')->skip($toSkip)->take($perPage)->get();
要做到這一點:
有沒有辦法從一個帖子的ID開始檢索前20個帖子,同時按排名排序
我不知道我是否正確,但你不能只使用where('id','>',$ id)?
編輯:nvm,您希望對所有結果進行分頁,以便您無法在哪里使用。
我原以為你可以通過將當前的id轉換為排名,然后在rank上添加where子句並最終獲取所需的記錄數來解決這個問題。
$posts = Post::with(array('user'=>function($q){
$q->select('id', 'img','nick', 'points', 'slug');
}))
->with('categories')
->with('voted')
->where('rank', '>', function($q) use ($id){
$q->select('rank')
->from('posts')
->where('id', $id);
})
->orderBy('rank', 'DESC')
->orderBy('created_at','DESC')
->take(20);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.