URL-адрес красивой страницы Laravel

Есть ли способ получить красивый URL-адрес страницы в Laravel 4?

Например, по умолчанию:

http://example.com/something/?page=3

И что я хотел бы получить:

http://example.com/something/page/3

Кроме того, разбиение на страницы должно отображаться таким образом, и добавление к разбивке на страницы должно отображаться таким образом.

Ответы

Ответ 1

Вот хакерское обходное решение. Я использую 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');
    }
}

Ответ 2

Это возможно, но вам нужно немного закодировать.

Сначала вам нужно изменить в app/config/app.php поставщик услуг pagination - вам нужно написать свой собственный.

Комментарий:

// 'Illuminate\Pagination\PaginationServiceProvider',

и добавьте

'Providers\PaginationServiceProvider',

в разделе поставщиков.

Теперь вам нужно создать свой PaginationServiceProvider для использования пользовательской разбивки на страницы factory:

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' => '[email protected]'
    ])->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 класса только для реализации одного метода.

Ответ 3

надеюсь, что это полезно для кого-то, я сделал черту, которая будет использоваться в моделях. Идея состоит в том, что этот пользовательский метод может определять текущий маршрут и настраивать ссылки для использования правильной позиции сегмента для параметра {page}:

https://gist.github.com/zofe/ced0054e6ac6eff1ea95

Ответ 4

Возможно, вы можете сделать какую-то причудливую маршрутизацию, чтобы заставить ее работать. Где-то рядом:

Route::get('something/{page}', function($page)
{
  //
})
->where('page', '[0-9]+');

В этом примере взяты из документа здесь.

Ответ 5

Единственный способ, которым я могу это сделать, - это расширить класс Paginator, чтобы выполнить сопоставление. Однако просто знайте, что это может противоречить сторонним пакетам и другим классам/библиотекам. Текущий метод предназначен для работы практически со всеми классами/библиотеками/пакетами.

Возможно, вы могли бы попробовать следующее:

http://packalyst.com/packages/package/desmart/pagination ('pagination' by 'desmart')