很早就想记录一下,但是直到今天才有时间,目的就是希望大家可以避坑,下面进入正文
默认使用model方法paginate作为分页,其实laravel 里面已经做了很多处理,作为开发者来讲其实就想简简单单的调方法而已,但是事与愿违,总会有特殊的定制,下面就来讲讲怎么定义不一样的html
找到模版
找到Illuminate\Database\Eloquent\Builder.php类中的对应方法,实际上实例化的是LengthAwarePaginator这个类,传入了一些基本分页信息,
再根据namespace继续追代码 Illuminate\Pagination\LengthAwarePaginator
想到在视图中使用render 来渲染html代码,则观察下面方法
public function render(Presenter $presenter = null)
{
if (is_null($presenter) && static::$presenterResolver) {
$presenter = call_user_func(static::$presenterResolver, $this);
}
$presenter = $presenter ?: new BootstrapThreePresenter($this);
return $presenter->render();
}
看后面的代码可以知道这个Presenter 其实就是一个模版对象,这里暂且这样理解
创建自己的模版
下面有几个坑要注意
下面都以BootstrapThreePresenter举例
继承PresenterContract
\Illuminate\Contracts\Pagination\Presenter
观察 LengthAwarePaginator 类的同级目录下会发现好多个Presenter的类,我们打开 BootstrapThreePresenter 这个类就会发现继承了上面的这个Presenter接口,因为在其他的地方会有类型约束,也为了和laravel本身框架的代码风格保持一致,所以后面我们定义的模版也继承就可以了
生成html结构
恶心的地方来了。。。
这里引入了traits所以结构有些混乱,你别看定义了好几个方法,但是protected全tm在traits里面调用,我们看最主要的渲染方法
public function render()
{
if ($this->hasPages()) {
return sprintf(
'<ul class="pagination">%s %s %s</ul>', //定义html容器
$this->getPreviousButton(), //生成上一页按钮
$this->getLinks(), //生成中间的页码
$this->getNextButton() //生成下一页按钮
);
}
return '';
}
如果你还需要增加首页或者末页,只需要在<ul class="pagination">%s %s %s</ul>
里面额外定义字符串参数就可以了
调用与封装
接下来我把项目中现成的代码拷贝过来
调用的封装
/**
*
* @return string 分页Html代码
*/
function pagination(\Illuminate\Contracts\Pagination\Paginator $paginator, $template = 'simple')
{
//这里我定义了多个模版所以做了点处理
$class = '\App\Libraries\Common\Pagination\\'.ucfirst($template).'Presenter';
$paginator->setPath(request()->url());
return $paginator
->appends(request()->input())
->render(new $class($paginator)); //实例化把自己传进去 我觉得恶心的不行,感觉像自己日自己
}
//demo
$paginate = User::paginate();
pagination($paginate, 'ajax');
SimplePresenter.php
<?php
namespace App\Libraries\Common\Pagination;
use Illuminate\Pagination\BootstrapThreeNextPreviousButtonRendererTrait;
use Illuminate\Pagination\UrlWindowPresenterTrait;
use Illuminate\Pagination\UrlWindow;
use Illuminate\Contracts\Pagination\Paginator as PaginatorContract;
use Illuminate\Contracts\Pagination\Presenter as PresenterContract;
class SimplePresenter implements PresenterContract
{
//HeadTailButtonRendererTrait 这个是我自己定义的,用来创建首页与末页的按钮
use BootstrapThreeNextPreviousButtonRendererTrait, HeadTailButtonRendererTrait,
UrlWindowPresenterTrait;
/**
* The paginator implementation.
*
* @var \Illuminate\Contracts\Pagination\Paginator
*/
protected $paginator;
/**
* The URL window data structure.
*
* @var array
*/
protected $window;
/**
* Create a new Bootstrap presenter instance.
*
* @param \Illuminate\Contracts\Pagination\Paginator $paginator
* @param \Illuminate\Pagination\UrlWindow|null $window
* @return void
*/
public function __construct(PaginatorContract $paginator, UrlWindow $window = null)
{
$this->paginator = $paginator;
$this->window = is_null($window) ? UrlWindow::make($paginator) : $window->get();
}
/**
* Determine if the underlying paginator being presented has pages to show.
*
* @return bool
*/
public function hasPages()
{
return $this->paginator->hasPages();
}
/**
* Convert the URL window into Bootstrap HTML.
*
* @return string
*/
public function render()
{
if ($this->hasPages()) {
return sprintf(
'<div class="paging_box">%s %s %s %s %s</div>',
$this->getLinks(),
$this->getFirstButton('首页'),
$this->getPreviousButton('上一页'),
$this->getNextButton('下一页'),
$this->getLastButton('末页')
);
}
return '';
}
/**
* Get HTML wrapper for an available page link.
*
* @param string $url
* @param int $page
* @param string|null $rel
* @return string
*/
protected function getAvailablePageWrapper($url, $page, $rel = null)
{
$rel = is_null($rel) ? '' : ' rel="'.$rel.'"';
return '<a href="'.htmlentities($url).'"'.$rel.'>'.$page.'</a>';
}
/**
* Get HTML wrapper for disabled text.
*
* @param string $text
* @return string
*/
protected function getDisabledTextWrapper($text)
{
return '<a href="javascript:;">'.$text.'</a>';
}
/**
* Get HTML wrapper for active text.
*
* @param string $text
* @return string
*/
protected function getActivePageWrapper($text)
{
return '<a href="javascript:;" class="on">'.$text.'</a>';
}
/**
* Get a pagination "dot" element.
*
* @return string
*/
protected function getDots()
{
return $this->getDisabledTextWrapper('...');
}
/**
* Get the current page from the paginator.
*
* @return int
*/
protected function currentPage()
{
return $this->paginator->currentPage();
}
/**
* Get the last page from the paginator.
*
* @return int
*/
protected function lastPage()
{
return $this->paginator->lastPage();
}
}
我的方式可能不是最优雅的,也可能会有其他方法,但是我这里只介绍一个思路,不做其他尝试