[英]Pagination with Eloquent-5.3 using Slim 3
这是我的分页代码:
控制器:
public function index($request, $response) {
$current_page = $request->getParam('page');
Paginator::currentPageResolver(function() use ($current_page) {
return $current_page;
});
$routes = $this->route->paginate(2);
return $this->view->render($response, 'dashboard/dashboard.twig', [
'routes' => $routes
]);
}
视图:
{% for route in routes %}
{{ route.route_name }}<br>
{% endfor %}
当我运行浏览器时没有问题。 当我在网址中添加page
参数时,它也有效。
但是当我尝试在paginate对象中添加links
方法时。
{% for route in routes %}
{{ route.route_name }}<br>
{% endfor %}
{{ routes.links() }} {# <--- This one #}
它提示我一个错误
消息:在null上调用成员函数make()
文件:C:\\ xampp \\ htdocs ... \\ vendor \\ illuminate \\ pagination \\ LengthAwarePaginator.php
更新:
当我尝试回显Controller内的links()
方法时。 我发现了这个错误。
$routes = $this->route->paginate(5);
echo $routes->links();
die();
警告:call_user_func()期望参数1是有效的回调,没有在第377行的C:\\ xampp \\ htdocs ... \\ vendor \\ illuminate \\ pagination \\ AbstractPaginator.php中给出的数组或字符串
然后我检查了源代码,就是这个。
/**
* Get an instance of the view factory from the resolver.
*
* @return \Illuminate\Contracts\View\Factory
*/
public static function viewFactory()
{
return call_user_func(static::$viewFactoryResolver);
}
对此有何解决方案?
这个方法适用于5.2,参考这个链接。
但不幸的是,它不再起作用了。
在PHP 7中,您可以创建匿名类以注册它以在viewVactory中使用:
$view = $this->container->get('view');
$view->getEnvironment()->addTest(new Twig_SimpleTest('string', function($value) {
return is_string($value);
}));
\Illuminate\Pagination\Paginator::viewFactoryResolver(function() use ($view) {
return new class($view) {
private $view;
private $template;
private $data;
public function __construct(\Slim\Views\Twig $view)
{
$this->view = $view;
}
public function make(string $template, $data = null)
{
$this->template = $template;
$this->data = $data;
return $this;
}
public function render()
{
return $this->view->fetch($this->template, $this->data);
}
};
});
\Illuminate\Pagination\Paginator::currentPageResolver(function() use ($request) {
return $request->getParam('page');
});
return $view->render($response, 'list.twig', [
'items' => Material::paginate(10),
]);
在list.twig
:
{{ items.render('pagination.twig') | raw }}
在pagination.twig
:
{% if paginator.hasPages() %}
<ul class="pagination">
{% for element in elements %}
{% if element is string %}
<li class="disabled"><span>{{ element }}</span></li>
{% endif %}
{% if element is iterable %}
{% for page, url in element %}
{% if page == paginator.currentPage() %}
<li class="active"><span>{{ page }}</span></li>
{% else %}
<li><a href="{{ url }}">{{ page }}</a></li>
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
</ul>
{% endif %}
我不得不使用上面的答案组合来完成一些工作。 我会在这里发布我的解决方案,以防它帮助别人。
这是Wesley的模板,但升级为使用bootstrap 4.作为奖励,它不需要中间件来设置任何全局变量。
// pagination.twig
{% if data is not empty and data.lastPage > 1 %}
{# Pagination shows a "window" of links to the left and right of the current page #}
{% set num_visible_pages = 20 %}
<ul class="pagination">
<li class="page-item {{ (data.currentPage == 1) ? 'disabled' : '' }}">
<a class="page-link" href="{{ data.url(1) }}">First</a>
</li>
{% for page_number in 1..(data.lastPage) %}
{% set half_visible_links = num_visible_pages / 2 | round %}
{% set from = data.currentPage - half_visible_links %}
{% set to = data.currentPage + half_visible_links %}
{# if near beginning of pages, extend end to ensure num_visible_pages are shown #}
{% if data.currentPage < half_visible_links %}
{# we can be sloppy because the loop iteration constrains-out-of-bounds values #}
{% set to = (half_visible_links - data.currentPage) + to %}
{% endif %}
{# if near end of pages, extend beginning to ensure num_visible_pages are shown #}
{% if (data.lastPage - data.currentPage) < half_visible_links %}
{# we can be sloppy because the loop iteration constrains-out-of-bounds values #}
{% set from = data.lastPage - num_visible_pages %}
{% endif %}
{# only print pages between "from" and "to" #}
{% if from < page_number and page_number < to %}
<li class="page-item {{ (data.currentPage == page_number) ? 'active' : '' }}">
<a class="page-link" href="{{ data.url(page_number) }}">{{ page_number }}</a>
</li>
{% endif %}
{% endfor %}
<li class="page-item {{ (data.currentPage == data.lastPage) ? 'disabled' : '' }}">
<a class="page-link" href="{{ data.url(data.lastPage) }}">Last</a>
</li>
</ul>
{% endif %}
你可以在你的twig模板中调用这样的东西,其中“items”是paginator查询的结果。
{% include 'pagination.twig'
with {data: items} only
%}
然后,你需要告诉Eloquent Paginator如何从网址获取“页面”(否则你将被困在第1页)。 您可以通过在paginator()查询之前调用currentPageResolver()来执行此操作。 对我来说,我只是把它放到一些中间件中,所以它总是被定义。
<?php
/**
* Tells the Eloquent Paginator how to get the current page
*/
namespace App\Middleware;
class Pagination {
public function __invoke($request, $response, $next)
{
\Illuminate\Pagination\Paginator::currentPageResolver(function() use ($request) {
return $request->getParam('page');
});
return $next($request, $response);
}
}
让Slim在您的应用设置中了解它的中间件。
$app->add(new App\Middleware\Pagination);
您可能希望向网址添加更多参数,例如排序或切换数据。 您仍然可以使用$items->appends()
来执行此操作。 请注意,默认路径为“/”。 您可以使用$items->withPath('')
删除它,因此使用->url()
生成的->url()
将链接到当前页面。
作为临时解决方案,我似乎可以访问paginate对象的方法。 所以我试图在互联网上找到一个分页的laravel模板。
这是我提出的解决方案。
它的作用是,它只显示数组是否为空,显然它是否呈现多个页面。 (取决于您在分页中设置的页数)
我从某个地方获得的模板具有适合我需要的修改功能。
{% if arrays is not empty and arrays.lastPage > 1 %}
<div class="paginate-wrapper">
<ul class="pagination">
<li class="{{ (arrays.currentPage == 1) ? 'active' : '' }}">
<a href="{{ uri.link }}{{ (uri.request_sent) ? '&' : '?' }}page=1">First</a>
</li>
{% for page_number in 1..(arrays.lastPage) %}
{% set half_total_links = 7 / 2 | round %}
{% set from = arrays.currentPage - half_total_links %}
{% set to = arrays.currentPage + half_total_links %}
{% if arrays.currentPage < half_total_links %}
{% set to = (half_total_links - arrays.currentPage) + to %}
{% endif %}
{% if (arrays.lastPage - arrays.currentPage) < half_total_links %}
{% set from = (half_total_links - (arrays.lastPage - arrays.currentPage) - 1) - to %}
{% endif %}
{% if from < page_number and page_number < to %}
<li class="{{ (arrays.currentPage == page_number) ? 'active' : '' }}">
<a href="{{ uri.link }}{{ (uri.request_sent) ? '&' : '?' }}page={{ page_number }}">{{ page_number }}</a>
</li>
{% endif %}
{% endfor %}
<li class="{{ (arrays.currentPage == arrays.lastPage) ? 'active' : '' }}">
<a href="{{ uri.link }}{{ (uri.request_sent) ? '&' : '?' }}page={{ arrays.lastPage }}">
Last
</a>
</li>
</ul>
</div>
{% endif %}
这是我在路由器上的中间件。
namespace App\Middleware;
use Illuminate\Database\Capsule\Manager as DB;
use App\Models\Module\Module;
class RouterMiddleware extends Middleware {
public function __invoke($request, $response, $next) {
$uri = $request->getUri();
$current_path = $uri->getPath();
$route = $request->getAttribute('route');
if ($route) {
$route_name = $route->getName();
$uri_page_parameter = $request->getParam('page');
// We want to retrieve the whole url including all the get parameters to get the current url itself
// Excluding page (pagination) parameter.
if ($uri_page_parameter != '') {
$uri = str_replace(['?page=' . $uri_page_parameter, '&page=' . $uri_page_parameter], '', $uri);
}
// We'll also check if the request has been sent using get method
$uri_request_sent = explode('?', $uri);
// Route Information
$this->container->view->getEnvironment()->addGlobal('uri', [
'link' => $uri,
'request_sent' => (isset($uri_request_sent[1])) ? true : false
]);
$this->container->view->getEnvironment()->addGlobal('current_route', $route_name);
$this->container->view->getEnvironment()->addGlobal('current_path', $current_path);
}
$response = $next($request, $response);
return $response;
}
}
它的作用是,每次搜索某些内容时,当您更改页面时,您发送的所有请求都不会消失。
在你的控制器中,你可以这样做:
$routes = $this->route->paginate(5);
$window = Illuminate\Pagination\UrlWindow::make($routes);
$elements = [
$window['first'],
is_array($window['slider']) ? '...' : null,
$window['slider'],
is_array($window['last']) ? '...' : null,
$window['last'],
];
// $this->twig is an instance of \Twig_Environment
// before render the template below, you should add `is_array` and `is_string` funcion to twig first
$this->twig->addFunction('is_string', new \Twig_SimpleFunction('is_string', function ($val) {
return is_string($val);
}));
$this->twig->addFunction('is_array', new \Twig_SimpleFunction('is_array', function ($val) {
return is_array($val);
}));
echo $this->twig->render(
'pageNav.html',
['paginator' => $routes, 'elements' => array_filter($elements)]
);
您的模板文件(pageNav.html)将如下所示:
{% if paginator.hasPages %}
<ul class="am-pagination">
{% if paginator.onFirstPage %}
<li class="am-disabled"><span>«</span></li>
{% else %}
<li><a href="{{ paginator.previousPageUrl }}" rel="prev">«</a></li>
{% endif %}
{% for element in elements %}
{% if is_string(element) %}
<li class="am-disabled"><span>{{ element }}</span></li>
{% endif %}
{% if is_array(element) %}
{% for page, url in element %}
{% if paginator.currentPage == page %}
<li class="am-active"><span>{{ page }}</span></li>
{% else %}
<li><a href="{{ url }}">{{ page }}</a></li>
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% if paginator.hasMorePages %}
<li><a href="{{ paginator.nextPageUrl }}" rel="next">»</a></li>
{% else %}
<li class="am-disabled"><span>»</span></li>
{% endif %}
</ul>
{% endif %}
祝好运:)
有一点问题:
{% if (data.lastPage - data.currentPage) < half_total_links %}
{% set from = (half_total_links - (data.lastPage - data.currentPage) - 1) - to %}
{% endif %}
当data.lastPage
和data.currentPage
相等时,变量from
为负数。
我修好了:
{% if from < 0 %}
{% set from = pagination.page - half_total_links %}
{% endif %}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.