Prologo
Primi Passi
Architettura
Le Basi
- Routing
- Middleware
- Protezione da CSRF
- Controller
- Richieste
- Risposte
- Views
- Blade
- Vite
- URL
- Sessioni
- Validazione
- Errori
- Logging
Approfondimenti
- Artisan
- Broadcasting
- Cache
- Collezioni
- Concorrenza
- Contesto
- Contratti
- Eventi
- File System
- Helpers
- Client HTTP
- Localizzazione
- Notifiche
- Sviluppo di Package
- Processi
- Code
- Rate-limiting
- Stringhe
- Scheduling di Task
Sicurezza
Database
Eloquent ORM
Testing
Package
Paginazione
- Introduzione
- Uso di base
- Visualizzazione dei Risultati di Paginazione
- Personalizzazione della Vista di Paginazione
- Metodi di Istanza di Paginator / LengthAwarePaginator
- Metodi delle Instance del Cursor Paginator
Introduzione
Nei altri framework, la paginazione può essere molto complicata. L’approccio di Laravel alla paginazione sarà sicuramente un respiro d’aria fresca. Il paginator di Laravel è integrato con il query builder e Eloquent ORM e offre una paginazione comoda e facile da usare dei record del database senza configurazioni.
Per impostazione predefinita, l’HTML generato dal paginator è compatibile con il framework Tailwind CSS; tuttavia, è disponibile anche il supporto alla paginazione di Bootstrap.
Tailwind JIT
Se stai usando le viste di paginazione predefinite di Tailwind di Laravel e il motore Tailwind JIT, assicurati che la chiave content
nel file tailwind.config.js
della tua applicazione faccia riferimento alle viste di paginazione di Laravel, in modo che le loro classi Tailwind non vengano rimosse:
content: [
'./resources/**/*.blade.php',
'./resources/**/*.js',
'./resources/**/*.vue',
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
],
Uso di base
Paginare i Risultati del Query Builder
Ci sono diversi modi per paginare gli elementi. Il più semplice è utilizzare il metodo paginate
sul query builder o su una query Eloquent. Il metodo paginate
si occupa automaticamente di impostare il "limit" e l’"offset" della query in base alla pagina corrente visualizzata dall’utente. Per impostazione predefinita, la pagina corrente viene rilevata dal valore dell’argomento della stringa di query page
nella richiesta HTTP. Questo valore viene rilevato automaticamente da Laravel e inserito automaticamente nei link generati dal paginator.
In questo esempio, l’unico argomento passato al metodo paginate
è il numero di elementi che desideri visualizzare "per pagina". In questo caso, specifichiamo che desideriamo visualizzare 15
elementi per pagina:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
class UserController extends Controller
{
/**
* Mostra tutti gli utenti dell'applicazione.
*/
public function index(): View
{
return view('user.index', [
'users' => DB::table('users')->paginate(15)
]);
}
}
Paginazione Semplice
Il metodo paginate
conta il numero totale di record corrispondenti alla query prima di recuperarli dal database. Questo permette al paginator di sapere quante pagine di record esistono in totale. Tuttavia, se non prevedi di mostrare il numero totale di pagine nell’interfaccia della tua applicazione, la query per contare i record non è necessaria.
Quindi, se hai bisogno solo di mostrare semplici link "Successivo" e "Precedente" nell’interfaccia della tua applicazione, puoi utilizzare il metodo simplePaginate
per eseguire una query unica ed efficiente:
$users = DB::table('users')->simplePaginate(15);
Paginare i risultati di Eloquent
Puoi anche paginare le query Eloquent. In questo esempio, pagineremo il modello App\Models\User
e specificheremo che vogliamo mostrare 15 record per pagina. Come vedi, la sintassi è quasi identica a quella per paginare i risultati del query builder:
use App\Models\User;
$users = User::paginate(15);
Naturalmente, puoi chiamare il metodo paginate
dopo aver impostato altri vincoli sulla query, come clausole where
:
$users = User::where('votes', '>', 100)->paginate(15);
Puoi anche utilizzare il metodo simplePaginate
quando pagini modelli Eloquent:
$users = User::where('votes', '>', 100)->simplePaginate(15);
Allo stesso modo, puoi usare il metodo cursorPaginate
per paginare con cursore i modelli Eloquent:
$users = User::where('votes', '>', 100)->cursorPaginate(15)
Più istanze di paginator per pagina
A volte potresti aver bisogno di mostrare due paginator separati in una singola schermata gestita dalla tua applicazione. Tuttavia, se entrambe le istanze di paginator usano il parametro della query string page
per memorizzare la pagina corrente, i due paginator entreranno in conflitto. Per risolvere questo conflitto, puoi passare il nome del parametro della query string che desideri utilizzare per memorizzare la pagina corrente del paginator tramite il terzo argomento fornito ai metodi paginate
, simplePaginate
e cursorPaginate
:
use App\Models\User;
$users = User::where('votes', '>', 100)->paginate(
$perPage = 15, $columns = ['*'], $pageName = 'users'
);
Paginazione con Cursor
Mentre paginate
e simplePaginate
creano query utilizzando la clausola "offset" di SQL, la paginazione con cursor funziona costruendo clausole "where" che confrontano i valori delle colonne ordinate presenti nella query, offrendo le prestazioni del database più efficienti disponibili tra tutti i metodi di paginazione di Laravel. Questo metodo di paginazione è particolarmente adatto per grandi insiemi di dati e interfacce utente con scorrimento "infinito".
A differenza della paginazione basata su offset, che include un numero di pagina nella stringa di query degli URL generati dal paginator, la paginazione basata su cursor inserisce una stringa "cursor" nella stringa di query. Il cursor è una stringa codificata che contiene la posizione da cui la prossima query paginata dovrebbe iniziare a paginare e la direzione in cui dovrebbe paginare:
http://localhost/users?cursor=eyJpZCI6MTUsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0
Puoi creare un’istanza paginator basata su cursor tramite il metodo cursorPaginate
offerto dal query builder. Questo metodo restituisce un’istanza di Illuminate\Pagination\CursorPaginator
:
$users = DB::table('users')->orderBy('id')->cursorPaginate(15);
Una volta ottenuta un’istanza del paginator con cursor, puoi mostrare i risultati della paginazione come faresti normalmente utilizzando i metodi paginate
e simplePaginate
. Per ulteriori informazioni sui metodi dell’istanza offerti dal cursor paginator, consulta la documentazione dei metodi dell’istanza del cursor paginator.
La tua query deve contenere una clausola "order by" per usufruire della paginazione con cursor. Inoltre, le colonne con cui la query è ordinata devono appartenere alla tabella che stai paginando.
Paginazione con Cursor vs Offset
Per illustrare le differenze tra la paginazione offset e quella con cursor, esaminiamo alcune query SQL di esempio. Entrambe le seguenti query mostreranno la "seconda pagina" di risultati per una tabella users
ordinata per id
:
# Paginazione Offset
select * from users order by id asc limit 15 offset 15;
# Paginazione con cursore...
select * from users where id > 15 order by id asc limit 15;
La query di paginazione con cursore offre i seguenti vantaggi rispetto alla paginazione con offset:
- Per grandi dataset, la paginazione con cursore offrirà migliori prestazioni se le colonne "order by" sono indicizzate. Questo perché la clausola "offset" scansiona tutti i dati precedentemente corrispondenti.
- Per dataset con scritture frequenti, la paginazione con offset potrebbe saltare record o mostrare duplicati se i risultati sono stati recentemente aggiunti o eliminati dalla pagina che l’utente sta visualizzando.
Tuttavia, la paginazione con cursore ha le seguenti limitazioni:
- Come
simplePaginate
, la paginazione con cursore può essere utilizzata solo per mostrare i link "Next" e "Previous" e non supporta la generazione di link con numeri di pagina. - Richiede che l’ordinamento sia basato su almeno una colonna unica o su una combinazione di colonne uniche. Le colonne con valori
null
non sono supportate. - Le espressioni di query nelle clausole "order by" sono supportate solo se sono alias e aggiunte anche alla clausola "select".
- Le espressioni di query con parametri non sono supportate.
Creare Manualmente un Paginator
A volte potresti voler creare un’istanza di paginazione manualmente, passando un array di elementi che hai già in memoria. Puoi farlo creando un’istanza di Illuminate\Pagination\Paginator
, Illuminate\Pagination\LengthAwarePaginator
o Illuminate\Pagination\CursorPaginator
, a seconda delle tue esigenze.
Le classi Paginator
e CursorPaginator
non hanno bisogno di conoscere il numero totale di elementi nel set di risultati; tuttavia, per questo motivo, non dispongono di metodi per ottenere l’indice dell’ultima pagina. Il LengthAwarePaginator
accetta quasi gli stessi argomenti del Paginator
, ma richiede un conteggio totale degli elementi nel set di risultati.
In altre parole, il Paginator
corrisponde al metodo simplePaginate
del query builder, il CursorPaginator
al metodo cursorPaginate
e il LengthAwarePaginator
al metodo paginate
.
Quando crei manualmente un’istanza di paginator, dovresti "tagliare" manualmente l’array dei risultati che passi al paginator. Se non sei sicuro di come farlo, consulta la funzione PHP array_slice.
Personalizzare gli URL di Paginazione
Per impostazione predefinita, i link generati dal paginatore corrisponderanno all’URI della richiesta corrente. Tuttavia, il metodo withPath
del paginatore ti permette di personalizzare l’URI utilizzato quando vengono generati i link. Ad esempio, se vuoi che il paginatore generi link come http://example.com/admin/users?page=N
, devi passare /admin/users
al metodo withPath
:
use App\Models\User;
Route::get('/users', function () {
$users = User::paginate(15);
$users->withPath('/admin/users');
// ...
});
Aggiungere Valori alla Query String
Puoi aggiungere alla query string dei link di paginazione usando il metodo appends
. Ad esempio, per aggiungere sort=votes
a ogni link di paginazione, dovresti chiamare appends
nel seguente modo:
use App\Models\User;
Route::get('/users', function () {
$users = User::paginate(15);
$users->appends(['sort' => 'votes']);
// ...
});
Puoi usare il metodo withQueryString
se desideri aggiungere tutti i valori della query string della richiesta corrente ai link di paginazione:
$users = User::paginate(15)->withQueryString();
Aggiungere frammenti hash
Se hai bisogno di aggiungere un "frammento hash" agli URL generati dal paginator, puoi usare il metodo fragment
. Ad esempio, per aggiungere #users
alla fine di ogni link di paginazione, devi chiamare il metodo fragment
in questo modo:
$users = User::paginate(15)->fragment('users');
Visualizzazione dei Risultati di Paginazione
Quando chiami il metodo paginate
, riceverai un’istanza di Illuminate\Pagination\LengthAwarePaginator
, mentre chiamando il metodo simplePaginate
restituisce un’istanza di Illuminate\Pagination\Paginator
. Infine, chiamando il metodo cursorPaginate
ottieni un’istanza di Illuminate\Pagination\CursorPaginator
.
Questi oggetti forniscono diversi metodi che descrivono il set di risultati. Oltre a questi metodi di supporto, le istanze del paginator sono iterabili e possono essere percorse come un array. Quindi, una volta recuperati i risultati, puoi mostrarli e renderizzare i link delle pagine usando Blade:
<div class="container">
@foreach ($users as $user)
{{ $user->name }}
@endforeach
</div>
{{ $users->links() }}
Il metodo links
renderizzerà i link alle altre pagine del set di risultati. Ognuno di questi link conterrà già la corretta variabile di query string page
. Ricorda, l’HTML generato dal metodo links
è compatibile con il framework Tailwind CSS.
Regolare la Finestra dei Link di Paginazione
Quando il paginator mostra i link di paginazione, viene visualizzato il numero della pagina corrente insieme ai link per le tre pagine prima e dopo. Utilizzando il metodo onEachSide
, puoi controllare quanti link aggiuntivi vengono mostrati su ciascun lato della pagina corrente all’interno della finestra centrale mobile di link generata dal paginator:
{{ $users->onEachSide(5)->links() }}
Conversione dei Risultati in JSON
Le classi paginator di Laravel implementano il contratto dell’interfaccia Illuminate\Contracts\Support\Jsonable
ed espongono il metodo toJson
, quindi è molto semplice convertire i tuoi risultati di paginazione in JSON. Puoi anche convertire un’istanza di paginator in JSON restituendola da una route o da un’azione di un controller:
use App\Models\User;
Route::get('/users', function () {
return User::paginate();
});
Il JSON del paginator includerà informazioni meta come total
, current_page
, last_page
e altro. I record dei risultati sono disponibili tramite la chiave data
nell’array JSON. Ecco un esempio del JSON creato restituendo un’istanza di paginator da una route:
{
"total": 50,
"per_page": 15,
"current_page": 1,
"last_page": 4,
"first_page_url": "http://laravel.app?page=1",
"last_page_url": "http://laravel.app?page=4",
"next_page_url": "http://laravel.app?page=2",
"prev_page_url": null,
"path": "http://laravel.app",
"from": 1,
"to": 15,
"data":[
{
// Record...
},
{
// Record...
}
]
}
Personalizzazione della Vista di Paginazione
Di default, le viste renderizzate per visualizzare i link di paginazione sono compatibili con il framework Tailwind CSS. Tuttavia, se non usi Tailwind, puoi definire le tue viste per renderizzare questi link. Quando chiami il metodo links
su un’istanza paginator, puoi passare il nome della vista come primo argomento al metodo:
{{ $paginator->links('view.name') }}
<!-- Passing additional data to the view... -->
{{ $paginator->links('view.name', ['foo' => 'bar']) }}
Tuttavia, il modo più semplice per personalizzare le viste di paginazione è esportarle nella directory resources/views/vendor
usando il comando vendor:publish
:
php artisan vendor:publish --tag=laravel-pagination
Questo comando posizionerà le viste nella directory resources/views/vendor/pagination
della tua applicazione. Il file tailwind.blade.php
all’interno di questa directory corrisponde alla vista di paginazione di default. Puoi modificare questo file per cambiare l’HTML della paginazione.
Se desideri designare un file diverso come vista di paginazione predefinita, puoi invocare i metodi defaultView
e defaultSimpleView
del paginator all’interno del metodo boot
della tua classe App\Providers\AppServiceProvider
:
<?php
namespace App\Providers;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Paginator::defaultView('view-name');
Paginator::defaultSimpleView('view-name');
}
}
Utilizzo di Bootstrap
Laravel include le viste di paginazione costruite con Bootstrap CSS. Per utilizzare queste viste invece delle viste predefinite di Tailwind, puoi chiamare i metodi useBootstrapFour
o useBootstrapFive
del paginator all’interno del metodo boot
della tua classe App\Providers\AppServiceProvider
:
use Illuminate\Pagination\Paginator;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Paginator::useBootstrapFive();
Paginator::useBootstrapFour();
}
Metodi di Istanza di Paginator / LengthAwarePaginator
Ogni istanza di paginator fornisce informazioni aggiuntive sulla paginazione tramite i seguenti metodi:
Metodo | Descrizione |
---|---|
$paginator->count() |
Ottiene il numero di elementi per la pagina corrente. |
$paginator->currentPage() |
Ottiene il numero della pagina corrente. |
$paginator->firstItem() |
Ottiene il numero del primo elemento nei risultati. |
$paginator->getOptions() |
Ottiene le opzioni del paginator. |
$paginator->getUrlRange($start, $end) |
Crea un intervallo di URL di paginazione. |
$paginator->hasPages() |
Verifica se ci sono abbastanza elementi per suddividerli in più pagine. |
$paginator->hasMorePages() |
Verifica se ci sono più elementi nell’archivio dati. |
$paginator->items() |
Ottiene gli elementi della pagina corrente. |
$paginator->lastItem() |
Ottiene il numero dell’ultimo elemento nei risultati. |
$paginator->lastPage() |
Ottiene il numero dell’ultima pagina disponibile. (Non disponibile quando si usa simplePaginate ). |
$paginator->nextPageUrl() |
Ottiene l’URL per la pagina successiva. |
$paginator->onFirstPage() |
Verifica se il paginator si trova sulla prima pagina. |
$paginator->perPage() |
Il numero di elementi da mostrare per pagina. |
$paginator->previousPageUrl() |
Ottiene l’URL per la pagina precedente. |
$paginator->total() |
Determina il numero totale di elementi corrispondenti nell’archivio dati. (Non disponibile quando si usa simplePaginate ). |
$paginator->url($page) |
Ottiene l’URL per un numero di pagina specifico. |
$paginator->getPageName() |
Ottiene la variabile della query string usata per memorizzare la pagina. |
$paginator->setPageName($name) |
Imposta la variabile della query string usata per memorizzare la pagina. |
$paginator->through($callback) |
Trasforma ogni elemento usando una callback. |
Metodi delle Instance del Cursor Paginator
Ogni istanza del cursor paginator fornisce informazioni aggiuntive sulla paginazione tramite i seguenti metodi:
Metodo | Descrizione |
---|---|
$paginator->count() |
Ottieni il numero di elementi per la pagina corrente. |
$paginator->cursor() |
Ottieni l’istanza del cursore attuale. |
$paginator->getOptions() |
Ottieni le opzioni del paginator. |
$paginator->hasPages() |
Verifica se ci sono abbastanza elementi per dividere in più pagine. |
$paginator->hasMorePages() |
Verifica se ci sono altri elementi nel data store. |
$paginator->getCursorName() |
Ottieni la variabile della query string utilizzata per memorizzare il cursore. |
$paginator->items() |
Ottieni gli elementi per la pagina corrente. |
$paginator->nextCursor() |
Ottieni l’istanza del cursore per il set successivo di elementi. |
$paginator->nextPageUrl() |
Ottieni l’URL per la pagina successiva. |
$paginator->onFirstPage() |
Verifica se il paginator si trova sulla prima pagina. |
$paginator->onLastPage() |
Verifica se il paginator si trova sull’ultima pagina. |
$paginator->perPage() |
Il numero di elementi da mostrare per pagina. |
$paginator->previousCursor() |
Ottieni l’istanza del cursore per il set precedente di elementi. |
$paginator->previousPageUrl() |
Ottieni l’URL per la pagina precedente. |
$paginator->setCursorName() |
Imposta la variabile della query string utilizzata per memorizzare il cursore. |
$paginator->url($cursor) |
Ottieni l’URL per una data istanza del cursore. |