有没有办法在Laravel 4中获得一个分页漂亮的URL?
例如,默认情况下:
http://example.com/something/?page=3
我想得到什么:
http://example.com/something/page/3
此外,分页应该以这种方式呈现,并且追加分页应该以这种方式出现.
这是可能的,但你需要编写一些代码.
首先,您需要更改app/config/app.php
分页服务提供程序 - 您需要自己编写.
评论:
// 'Illuminate\Pagination\PaginationServiceProvider',
并添加
'Providers\PaginationServiceProvider',
在提供者部分.
现在您需要创建PaginationServiceProvider以使用自定义分页工厂:
model/Providers/PaginationServiceProvider.php
文件:
<?php namespace Providers; use Illuminate\Support\ServiceProvider; class PaginationServiceProvider extends ServiceProvider { /** * Indicates if loading of the provider is deferred. * * @var bool */ protected $defer = true; /** * Register the service provider. * * @return void */ public function register() { $this->app->bindShared('paginator', function ($app) { $paginator = new PaginationFactory($app['request'], $app['view'], $app['translator']); $paginator->setViewName($app['config']['view.pagination']); $app->refresh('request', $paginator, 'setRequest'); return $paginator; }); } /** * Get the services provided by the provider. * * @return array */ public function provides() { return array('paginator'); } }
在上面创建Providers\PaginationFactory
对象,所以现在我们需要创建这个文件:
model/providers/PaginationFactory.php
文件:
<?php namespace Providers; use Illuminate\Pagination\Factory; class PaginationFactory extends Factory { /** * Get a new paginator instance. * * @param array $items * @param int $total * @param int|null $perPage * @return \Illuminate\Pagination\Paginator */ public function make(array $items, $total, $perPage = null) { $paginator = new \Utils\Paginator($this, $items, $total, $perPage); return $paginator->setupPaginationContext(); } }
在这里你只创建\Utils\Paginator
对象所以现在让我们创建它:
model/Utils/Paginator.php
文件:
<?php namespace Utils; class Paginator extends \Illuminate\Pagination\Paginator { /** * Get a URL for a given page number. * * @param int $page * @return string */ public function getUrl($page) { $routeParameters = array(); if ($page > 1) { // if $page == 1 don't add it to url $routeParameters[$this->factory->getPageName()] = $page; } return \URL::route($this->factory->getCurrentUrl(), $routeParameters); } }
在这个文件中,我们最终覆盖了创建分页URL的默认方法.
我们假设你有这样定义的路线:
Route::get('/categories/{page?}', ['as' => 'categories', 'uses' => 'CategoryController@displayList' ])->where('page', '[1-9]+[0-9]*');
如你所见,我们在这里定义了路由名称as
(由于上面的Paginator实现很重要 - 但你当然可以用不同的方式来实现).
现在,在方法displayList
的CategoryController
类,你可以这样做:
public function displayList($categories, $page = 1) // default 1 is needed here { Paginator::setCurrentPage($page); Paginator::setBaseUrl('categories'); // use here route name and not the url Paginator::setPageName('page'); $categories = Category::paginate(15); return View::make('admin.category')->with( ['categories' => $categories] ); }
在您的视图中添加:
<?php echo $categories->links(); ?>
您将以这种方式获得生成的URL:
http://localhost/categories http://localhost/categories/2 http://localhost/categories/3 http://localhost/categories/4 http://localhost/categories/5
没有?在查询字符串中
但是在我看来,默认情况下应该添加这样的东西,或者至少它应该足以扩展一个类而不是为了实现一个方法而创建3个类.
这是一个hacky解决方法.我正在使用Laravel v4.1.23.它假定页码是您网址的最后一位.没有深入测试,所以我对人们可以找到的任何错误感兴趣.我对更好的解决方案更感兴趣:-)
路线:
Route::get('/articles/page/{page_number?}', function($page_number=1){ $per_page = 1; Articles::resolveConnection()->getPaginator()->setCurrentPage($page_number); $articles = Articles::orderBy('created_at', 'desc')->paginate($per_page); return View::make('pages/articles')->with('articles', $articles); });
视图:
<?php $links = $articles->links(); $patterns = array(); $patterns[] = '/'.$articles->getCurrentPage().'\?page=/'; $replacements = array(); $replacements[] = ''; echo preg_replace($patterns, $replacements, $links); ?>
模型:
<?php class Articles extends Eloquent { protected $table = 'articles'; }
移民:
<?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateArticlesTable extends Migration { public function up() { Schema::create('articles', function($table){ $table->increments('id'); $table->string('slug'); $table->string('title'); $table->text('body'); $table->timestamps(); }); } public function down() { Schema::drop('articles'); } }