Laravel 5 - 查找模型的分页页面
Laravel 5 - Finding the pagination page for a model
我正在构建一个基本论坛(灵感来自 laracasts.com/discuss)。当用户 post 回复话题时:
- 我想将他们引导到 分页回复列表的末尾 以及他们回复的锚点(与 Laracasts 相同的行为)。
- 我还想 return 用户在编辑他们的回复时转到正确的页面。
如何确定新回复将 post 编辑到哪个页面 (?page=x
) 以及如何在编辑回复后 return 到正确的页面?或者,从主 post 列表中,最新回复在哪个页面上?
这是我当前的 ForumPost
模型(减去一些不相关的东西)-
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
/**
* Class ForumPost
*
* Forum Posts table
*
* @package App
*/
class ForumPost extends Model {
/**
* Post has many Replies
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function replies()
{
return $this->hasMany('App\ForumReply');
}
/**
* Get the latest reply for a post
* @return null
*/
public function latestReply()
{
return $this->replies()->orderBy('created_at', 'desc')->first();
}
}
更新
看看这个,让我知道你的想法。它的工作方式有点奇怪,但它return为给定的回复 ID 生成正确的页面,这只是一种方法:
public function getReplyPage($replyId = null, $paginate = 2)
{
$id = $replyId ? $replyId : $this->latestReply()->id;
$count = $this->replies()->where('id', '<', $id)->count();
$page = 1; // Starting with one page
// Counter - when we reach the number provided in $paginate, we start a new page
$offset = 0;
for ($i = 0; $i < $count; $i++) {
$offset++;
if ($offset == $paginate) {
$page++;
$offset = 0;
}
}
return $page;
}
从根本上说,您使用两个值:首先,回复的索引与 post 的所有回复相关,其次是页面上的回复数。
例如,您可能有一个 ID 为 301 的回复。但是,它是特定 post 上的第 21 个回复。您需要通过某种方式确定这是第 21 条回复。这实际上相对简单:您只需计算有多少回复与该 post 相关联,但 ID 较小。
//get the number of replies before the one you're looking for
public function getReplyIndex($replyId)
{
$count = $this->replies()->where('id', '<', $replyId)->count();
return $count;
}
该方法应该 return 您要查找的回复的索引 - 当然,假设您的回复使用的是自动递增 ID。
第二个难题是找出您需要的页面。这是使用 integer division 完成的。基本上你只是正常除数,但不要使用余数。如果您正在查看第 21 个回复,并且您对某个页面有 10 个回复,您知道它应该在第三页上(第 1 页:1-10,第 2 页:11-20,第 3 页:21-30)。这意味着您需要将回复索引除以每页回复数,然后加 1。这将得到 21/10+1,使用整数除法,得到 3。耶!
//divides where we are by the number of replies on a page and adds 1
public function getPageNumber($index, $repliesPerPage)
{
$pageNumber = (int) ($index/$repliesPerPage+1);
return $pageNumber;
}
好的,现在您只需拉出该页面即可。这只需要一个方法,您可以在其中指定所需的页码,以及对一个页面有多少回复。然后该方法可以计算偏移量和限制,并检索您需要的记录。
public function getPageOfReplies($pageNumber, $repliesPerPage)
{
$pageOfReplies = $this->replies()->offset($pageNumber*$repliesPerPage)->limit($repliesPerPage)->get();
return $pageOfReplies;
}
不过,为了更好的衡量,我们可以构建一个方法来获取最终回复的索引。
public function getLastReplyIndex()
{
$count = $this->replies()->count();
return $count;
}
太棒了!现在我们拥有了所需的所有构建块。我们可以构建一些简单的方法,使用我们更通用的方法来轻松检索我们需要的数据。
让我们从一个方法开始,该方法获取单个回复所在的整个回复页面(随意更改名称(我还假设每页有 10 个回复)):
public function getPageThatReplyIsOn($replyId)
{
$repliesPerPage = 10;
$index = $this->getReplyIndex($replyId);
$pageNumber = $this->getPageNumber($index, $repliesPerPage);
return $this->getPageOfReplies($pageNumber, $repliesPerPage);
}
为了更好的衡量,我们可以制作一个获取最终回复页面的方法。
public function getFinalReplyPage()
{
$repliesPerPage = 10;
$index = $this->getLastReplyIndex();
$pageNumber = $this->getPageNumber($index, $repliesPerPage);
return $this->getPageOfReplies($pageNumber, $repliesPerPage);
}
您可以构建各种其他方法来使用我们的构建块方法并跳转页面、获取回复之后或之前的页面等。
几个笔记
这些都在你的 ForumPost
模型中,它应该与你的回复有一对多的关系。
这些是旨在提供广泛功能的各种方法。不要害怕通读它们并单独测试它们以确切了解它们在做什么。 None 其中很长,所以应该不难。
这是我想到的。如果有人对此有任何改进建议,请告诉我。我真的很想知道是否有更多 Laravel 方法来做到这一点,我非常感谢 Jeffrey Way 分享他的秘密,因为他正在 Laracasts 做这件事。
/**
* Get Reply Page
*
* Returns the page number where a reply resides as it relates to pagination
*
* @param null $replyId Optional ID for specific reply
* @param bool $pageLink If True, return a GET parameter ?page=x
* @param int $paginate Number of posts per page
* @return int|null|string // Int for only the page number, null if no replies, String if $pageLink == true
*/
public function getReplyPage($replyId = null, $pageLink = false, $paginate = 20)
{
// Find the page for a specific reply if provided, otherwise find the most
// recent post's ID. If there are no replies, return null and exit.
if (!$replyId) {
$latestReply = $this->latestReply();
if ($latestReply) {
$replyId = $latestReply->id;
} else {
return null;
}
}
// Find the number of replies to this Post prior to the one in question
$count = $this->replies()->where('id', '<', $replyId)->count();
$page = CEIL($count / $paginate +1);
// Return either the integer or URL parameter
return $pageLink ? "?page=$page" : $page;
}
我正在构建一个基本论坛(灵感来自 laracasts.com/discuss)。当用户 post 回复话题时:
- 我想将他们引导到 分页回复列表的末尾 以及他们回复的锚点(与 Laracasts 相同的行为)。
- 我还想 return 用户在编辑他们的回复时转到正确的页面。
如何确定新回复将 post 编辑到哪个页面 (?page=x
) 以及如何在编辑回复后 return 到正确的页面?或者,从主 post 列表中,最新回复在哪个页面上?
这是我当前的 ForumPost
模型(减去一些不相关的东西)-
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
/**
* Class ForumPost
*
* Forum Posts table
*
* @package App
*/
class ForumPost extends Model {
/**
* Post has many Replies
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function replies()
{
return $this->hasMany('App\ForumReply');
}
/**
* Get the latest reply for a post
* @return null
*/
public function latestReply()
{
return $this->replies()->orderBy('created_at', 'desc')->first();
}
}
更新
看看这个,让我知道你的想法。它的工作方式有点奇怪,但它return为给定的回复 ID 生成正确的页面,这只是一种方法:
public function getReplyPage($replyId = null, $paginate = 2)
{
$id = $replyId ? $replyId : $this->latestReply()->id;
$count = $this->replies()->where('id', '<', $id)->count();
$page = 1; // Starting with one page
// Counter - when we reach the number provided in $paginate, we start a new page
$offset = 0;
for ($i = 0; $i < $count; $i++) {
$offset++;
if ($offset == $paginate) {
$page++;
$offset = 0;
}
}
return $page;
}
从根本上说,您使用两个值:首先,回复的索引与 post 的所有回复相关,其次是页面上的回复数。
例如,您可能有一个 ID 为 301 的回复。但是,它是特定 post 上的第 21 个回复。您需要通过某种方式确定这是第 21 条回复。这实际上相对简单:您只需计算有多少回复与该 post 相关联,但 ID 较小。
//get the number of replies before the one you're looking for
public function getReplyIndex($replyId)
{
$count = $this->replies()->where('id', '<', $replyId)->count();
return $count;
}
该方法应该 return 您要查找的回复的索引 - 当然,假设您的回复使用的是自动递增 ID。
第二个难题是找出您需要的页面。这是使用 integer division 完成的。基本上你只是正常除数,但不要使用余数。如果您正在查看第 21 个回复,并且您对某个页面有 10 个回复,您知道它应该在第三页上(第 1 页:1-10,第 2 页:11-20,第 3 页:21-30)。这意味着您需要将回复索引除以每页回复数,然后加 1。这将得到 21/10+1,使用整数除法,得到 3。耶!
//divides where we are by the number of replies on a page and adds 1
public function getPageNumber($index, $repliesPerPage)
{
$pageNumber = (int) ($index/$repliesPerPage+1);
return $pageNumber;
}
好的,现在您只需拉出该页面即可。这只需要一个方法,您可以在其中指定所需的页码,以及对一个页面有多少回复。然后该方法可以计算偏移量和限制,并检索您需要的记录。
public function getPageOfReplies($pageNumber, $repliesPerPage)
{
$pageOfReplies = $this->replies()->offset($pageNumber*$repliesPerPage)->limit($repliesPerPage)->get();
return $pageOfReplies;
}
不过,为了更好的衡量,我们可以构建一个方法来获取最终回复的索引。
public function getLastReplyIndex()
{
$count = $this->replies()->count();
return $count;
}
太棒了!现在我们拥有了所需的所有构建块。我们可以构建一些简单的方法,使用我们更通用的方法来轻松检索我们需要的数据。
让我们从一个方法开始,该方法获取单个回复所在的整个回复页面(随意更改名称(我还假设每页有 10 个回复)):
public function getPageThatReplyIsOn($replyId)
{
$repliesPerPage = 10;
$index = $this->getReplyIndex($replyId);
$pageNumber = $this->getPageNumber($index, $repliesPerPage);
return $this->getPageOfReplies($pageNumber, $repliesPerPage);
}
为了更好的衡量,我们可以制作一个获取最终回复页面的方法。
public function getFinalReplyPage()
{
$repliesPerPage = 10;
$index = $this->getLastReplyIndex();
$pageNumber = $this->getPageNumber($index, $repliesPerPage);
return $this->getPageOfReplies($pageNumber, $repliesPerPage);
}
您可以构建各种其他方法来使用我们的构建块方法并跳转页面、获取回复之后或之前的页面等。
几个笔记
这些都在你的 ForumPost
模型中,它应该与你的回复有一对多的关系。
这些是旨在提供广泛功能的各种方法。不要害怕通读它们并单独测试它们以确切了解它们在做什么。 None 其中很长,所以应该不难。
这是我想到的。如果有人对此有任何改进建议,请告诉我。我真的很想知道是否有更多 Laravel 方法来做到这一点,我非常感谢 Jeffrey Way 分享他的秘密,因为他正在 Laracasts 做这件事。
/**
* Get Reply Page
*
* Returns the page number where a reply resides as it relates to pagination
*
* @param null $replyId Optional ID for specific reply
* @param bool $pageLink If True, return a GET parameter ?page=x
* @param int $paginate Number of posts per page
* @return int|null|string // Int for only the page number, null if no replies, String if $pageLink == true
*/
public function getReplyPage($replyId = null, $pageLink = false, $paginate = 20)
{
// Find the page for a specific reply if provided, otherwise find the most
// recent post's ID. If there are no replies, return null and exit.
if (!$replyId) {
$latestReply = $this->latestReply();
if ($latestReply) {
$replyId = $latestReply->id;
} else {
return null;
}
}
// Find the number of replies to this Post prior to the one in question
$count = $this->replies()->where('id', '<', $replyId)->count();
$page = CEIL($count / $paginate +1);
// Return either the integer or URL parameter
return $pageLink ? "?page=$page" : $page;
}