Есть ли способ получить целевой URL-адрес страницы в Laravel 4?
Например, по умолчанию:
http://example.com/something/?page=3
И что я хотел бы получить:
http://example.com/something/page/3
Кроме того, разбиение на страницы должно отображаться таким образом, и добавление к разбивке на страницы должно отображаться таким образом.
Вот хакерское решение. Я использую Laravel v4.1.23. Он предполагает, что номер страницы – это последний бит вашего URL-адреса. Не проверял это глубоко, поэтому меня интересуют любые ошибки, которые могут найти люди. Меня больше интересует лучшее решение 🙂
Маршрут:
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'); } }
Это возможно, но вам нужно немного закодировать.
Сначала вам нужно изменить app/config/app.php
провайдер 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
объект Providers\PaginationFactory
, поэтому теперь нам нужно создать этот файл:
model/providers/PaginationFactory.php
файл 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 класса только для реализации одного метода.
надеюсь, что это полезно для кого-то, я сделал черту, которая будет использоваться в моделях. Идея заключается в том, что этот настраиваемый метод может определять текущий маршрут и настраивать ссылки для использования правильной позиции сегмента для параметра {page}:
Вероятно, вы могли бы сделать какую-то причудливую маршрутизацию, чтобы заставить работать. Где-то рядом:
Route::get('something/{page}', function($page) { // }) ->where('page', '[0-9]+');
Этот пример взят из документов здесь .
Единственный способ, которым я могу это сделать, – расширить класс Paginator, чтобы выполнить сопоставление. Однако просто знайте, что это может противоречить сторонним пакетам и другим классам / библиотекам. Текущий метод предназначен для работы практически со всеми классами / библиотеками / пакетами.
Возможно, вы могли бы попробовать следующее:
http://packalyst.com/packages/package/desmart/pagination ('pagination' от 'desmart')