2014-12-29 23 views
5

So versuche ich Paginierung in Laravel 5 mit hübschen URLs wie localhost/ads/1 zu erhalten, wo 1 für die Seite steht.Laravel 5 - Hübscher Paginator

Bis zu meinem Verständnis würde eine solche Operation eine Überlastung von AbstractPaginator oder LengthAwarePaginator erfordern, um eine Modifikation von Database\Query\Builder anzustreben.

Fehle ich etwas, eine Bindung oder eine Abhängigkeitsinjektion, oder sollte es die Möglichkeit geben, den Paginator zu ändern, den wir verwenden möchten?

+0

Könnten Sie 'mod_rewrite' verwenden zu konvertieren die URL zur richtigen Abfragezeichenfolge? Konvertiere es intern in 'localhost/ads? Page = 1'. –

+0

@BenHarold Sicher, das würde funktionieren um Links umzuleiten. Allerdings wird es das Problem der Generierung der Links nicht ändern, denke ich. – repptilia

Antwort

3

Am Ende musste ich mir einen Paginator selbst programmieren. Ich poste hier meine Lösung, sollte es jemandem helfen.

Beachten Sie, dass die Lösung, obwohl sie funktional ist, etwas Sorgfalt für den praktischen Gebrauch erfordert (zur Validierung); Die Klasse ist hier vereinfacht, um den Mechanismus hervorzuheben.

<?php namespace App\Services; 

use Illuminate\Support\Collection; 
use Illuminate\Pagination\BootstrapThreePresenter; 
use Illuminate\Pagination\LengthAwarePaginator as BasePaginator; 

class Paginator extends BasePaginator{ 



    /** 
    * Create a new paginator instance. 
    * 
    * @param mixed $items 
    * @param int $perPage 
    * @param string $path Base path 
    * @param int $page 
    * @return void 
    */ 
    public function __construct($items, $perPage, $path, $page){ 
     // Set the "real" items that will appear here 
     $trueItems = []; 

     // That is, add the correct items 
     for ($i = $perPage*($page-1) ; $i < min(count($items),$perPage*$page) ; $i++){ 
      $trueItems[] = $items[$i]; 
     } 

     // Set path as provided 
     $this->path = $path; 

     // Call parent 
     parent::__construct($trueItems,count($items),$perPage); 

     // Override "guessing" of page 
     $this->currentPage = $page; 
    } 

    /** 
    * Get a URL for a given page number. 
    * 
    * @param int $page 
    * @return string 
    */ 
    public function url($page){ 
     if ($page <= 0) $page = 1; 

     return $this->path.$page; 
    } 
} 

Um die Klasse zu verwenden, können Sie

Route::get('items/{page}','[email protected]'); 

Dann in der die Steuerung, in getElements eine Route definieren:

$items = new Paginator(Model::all(),$numberElementsPerPage,url('items'),$page); 

Dann können Sie, wie Sie Ihre Elemente entsorgen normalerweise würde. Hinweis: Ich habe eine Pfadoption hinzugefügt, um komplexere hübsche URL-Designs zu integrieren. Hoffe es hilft!

+1

Bedeutet das nicht, dass Sie die gesamte Tabelle in den Speicher laden müssen, bevor Sie die gewünschten Seiten paginieren können? – Puzbie

+0

'Model :: all' gibt das ganze Set zurück ... das ist Overkill, nicht wahr? – Toskan

-3

Entfernen Sie diese RewriteRule ^(.*)/$ /$1 [L,R=301] Codezeile von .htaccess.

+1

Diese Zeile hat nichts mit der Frage zu tun. – ceejayoz

1

Ich schrieb dies für Laravel 5.3 ohne Leistung Negative: PlumPrettyUrlPaginator.php

<?php 
namespace Plum\Cmc\Paginator; 

use Illuminate\Pagination\LengthAwarePaginator; 
use Illuminate\Support\Collection; 

class PlumPrettyUrlPaginator extends LengthAwarePaginator{ 

    /** 
    * basically a copy of LengthAwarePaginator constructor and then replacing all in our own 
    */ 
    public function __construct(LengthAwarePaginator $p, $path, $currentPage = null) { 

    $this->total = $p->total; 
    $this->perPage = $p->perPage; 
    $this->lastPage = (int) ceil($p->total/$p->perPage); 
// $this->path = ((stripos(strrev($p->path), '/') === 0) ? $p->path : $p->path.'/'); 
    $this->path = $path; 
    $this->currentPage = $p->setCurrentPage($currentPage ?? $p->currentPage, $p->pageName); 
    $this->items = $p->items; 
    } 

    public function url($page){ 
    if ($page <= 0) $page = 1; 
    return $this->path.$page; 
    } 
} 

Routen:

Route::get('/', [ function (Request $request) { 
    $data = PlumSearchService::PrepareSearchView($request); 
    return view('inventory.search_products', $data); 
}]); 


Route::get('/page/{pageNr}', [ function (Request $request, int $pageNr) { 
    $data = PlumSearchService::PrepareSearchView($request, false, $pageNr); 
    return view('inventory.search_products', $data); 
}]); 

dann im PlumSearchService

$query = Product::select('product.*') //... 
     $paginator = $query->paginate(15, ['*'], 'page', $pageNr); 
     $products = new PlumPrettyUrlPaginator($paginator, '/page/', $pageNr);