Laravel e React sono due popolari tecnologie di sviluppo Web utilizzate per la creazione di moderne applicazioni Web. Laravel è principalmente un framework PHP lato server, mentre React è una libreria JavaScript lato client. Questo tutorial funge da introduzione sia a Laravel che a React, combinandoli per creare una moderna applicazione web.
In una moderna applicazione web, il server ha il compito limitato di gestire il back-end attraverso degli API (Application Programming Interface) endpoint. Il client invia delle richieste a questi endpoint e il server restituisce delle risposte. Tuttavia, il server non si preoccupa di come il client renderizzerà la vista, il che è perfettamente in linea con il Separation of Concerns principle. Questa architettura consente agli sviluppatori di creare applicazioni robuste per il web e anche per i dispositivi mobile.
In questo tutorial, utilizzeremo Laravel 10 per creare un RESTful back-end API mentre il front-end comprenderà componenti scritti in React 18. Costruiremo un’applicazione che gestisce un catalogo prodotti. La prima parte del tutorial si concentrerà maggiormente sui concetti di Laravel e sul back-end.
Prerequisiti
Prima di iniziare, presumo che tu abbia una conoscenza di base dell’architettura RESTful e del funzionamento degli API endpoint. Inoltre, se hai una precedente esperienza in React o Laravel, sarai in grado di capirlo al volo.
Tuttavia, se sei nuovo in entrambi i framework, non preoccuparti. Il tutorial è scritto per principianti e dovresti essere in grado anche tu di capirlo senza problemi. Puoi trovare il codice sorgente per il tutorial su GitHub.
Installazione e configurazione del progetto Laravel
Prima di iniziare con Laravel, assicurati di aver installato Apache, MySQL, PHP e Composer sul tuo computer. Questo perché Laravel è basato su PHP e usa Composer per gestire tutte le dipendenze. Su Composer assicurati di scegliere l’opzione per aggiungerlo alla variabile di ambiente del percorso (path environment variable) in modo che Composer sia accessibile a livello globale.
Il progetto è stato configurato e testato su Apache 2.4.41, MySQL 8.0.33, PHP 8.2.6 e Composer 2.5.7. Come editor consigliamo di utilizzare Visual Studio Code.
Dovresti essere in grado di creare un nuovo progetto Laravel come segue:
1 |
composer create-project laravel/laravel impesud-app-backend
|
Se tutto è andato bene, dovresti essere in grado di pubblicare la tua applicazione su un server di sviluppo all’indirizzo https://localhost:8000.
1 |
php artisan serve
|
Artisan è uno strumento da riga di comando indispensabile per lavorare con Laravel. Artisan accetta un ampio elenco di comandi che ti consentono di creare del codice per la tua applicazione. Fai php artisan list
per visualizzare tutti i comandi artisan disponibili.
Configurazione dell’ambiente
La tua applicazione avrà un file .env all’interno della directory principale. Tutte le informazioni di configurazione specifiche dell’ambiente sono dichiarate qui. Crea un database per la tua applicazione se non lo hai già fatto e aggiungi i dettagli del database nel file .env.
1
2
3
4
5
6
|
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=impesud
DB_USERNAME=root
DB_PASSWORD=latuapassword
|
Qui stiamo collegando un database denominato impesud all’applicazione. Questo database è su MySQL, che è in esecuzione localmente sulla porta 3306. Il nome utente del database è root e la password è quella che hai impostato precedentemente.
Models, Routes e Controllers
Laravel è un framework che segue l’architettura Model-View-Controller (MVC). In generale, MVC ti aiuta a separare le query del database (Model) dalla logica relativa a come le richieste dovrebbero essere elaborate (Controller) e come il layout dovrebbe essere renderizzato (View).
Poiché stiamo costruendo un’API utilizzando Laravel, ci limiteremo al Model e al Controller in questa prima parte. Esamineremo le nostre opzioni per creare la View nella seconda parte di questo tutorial.
Router
Quando il server riceve una richiesta HTTP, Laravel tenta di abbinarla a un route registrato all’interno dei file routes. Tutti i file routes si trovano all’interno della directory route. route/web.php ospita la route per l’interfaccia web, mentre route/api.php ospita la route per l’API. Le routes registrate in api.php saranno precedute da /api
(localhost:3000/api). Se hai bisogno di modificare questo comportamento, puoi andare sulla classe RouteServiceProvider
in /app/Providers/RouteServiceProvider.php e apportare le modifiche lì.
Poiché stiamo costruendo un’applicazione per gestire un catalogo prodotti, gli endpoint per l’API e le azioni HTTP associate a tali endpoint saranno:
1
2
3
4
5
|
GET /products/: Recupera tutti i prodotti.
GET /product/{id}: Recupera il prodotto che corrisponde all'id.
POST /products: Crea un nuovo prodotto e lo inserisce nel database.
PUT /products/{id}: Aggiorna un prodotto esistente corrispondente all'id.
DELETE /products/{id}: Elimina il prodotto con l'ID specificato.
|
GET, POST, PUT e DELETE sono i verbi HTTP (più comunemente noti come metodi HTTP) fondamentali per creare un servizio RESTful. /products è l’URI associato alla risorsa dei prodotti. I metodi HTTP richiedono al server di eseguire l’azione desiderata su una determinata risorsa.
Di seguito è riportato il file route del progetto.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<strong>routes/api.php</strong>
<?php
use App\Http\Controllers\ProductsController;
/**
**Basic Routes for a RESTful service:
**Route::get($uri, $callback);
**Route::post($uri, $callback);
**Route::put($uri, $callback);
**Route::delete($uri, $callback);
**
*/
Route::get('products', [ProductsController::class, 'index']);
Route::get('products/{product}', [ProductsController::class, 'show']);
Route::post('products',[ProductsController::class, 'store']);
Route::put('products/{product}',[ProductsController::class, 'update']);
Route::delete('products/{product}', [ProductsController::class, 'delete']);
|
Se vuoi verificare che i percorsi funzionino come previsto, puoi utilizzare uno strumento come REST Client su Visual Studio Code. Assicurati che il server di sviluppo sia in esecuzione prima di interrogare gli API endpoint. A fine di questa prima parte potrai testarli correttamente. Ecco la risposta che ho ricevuto dall’interrogazione dell’API endpoint http://127.0.0.1:8000/api/products/1/
Model
La risorsa prodotti necessita di un Model in grado di interagire con il database. Il Model è il livello che si trova in cima al database, nascondendo tutto il gergo specifico del database. Laravel utilizza Eloquent ORM per modellare il database.
E la definizione dello schema del database? La migrazione di Laravel si occupa di questo. Artisan ha un comando di migrazione che ti consente di definire il tuo schema e di aggiornarlo in modo incrementale in una fase successiva. Creiamo un modello e una migrazione per l’entità Product.
1 |
php artisan make:model Product -m
|
Ecco il file di migrazione generato in database/migrations/timestamp_create_products_table.php:
Il metodo up viene chiamato durante la migrazione di nuove tabelle e colonne nel database, mentre il metodo down viene richiamato durante il rollback di una migrazione. Abbiamo creato uno schema per una tabella con tre righe: id, created_at e updated_at. Il metodo $table->timestamps() è responsabile del mantenimento delle colonne created_at e updated_at. Aggiungiamo un altro paio di righe alla definizione dello schema.
Abbiamo aggiornato lo schema con quattro nuove colonne. Il generatore di schemi di Laravel supporta una varietà di tipi di colonne come string, text, integer e boolean.
Per convenzione, Laravel presuppone che il modello Product sia associato alla tabella dei prodotti. Tuttavia, se è necessario associare il modello a un nome di tabella personalizzato, è possibile utilizzare la proprietà $table per dichiarare il nome della tabella.
Ma manterremo le cose semplici e seguiremo la convenzione. Il modello Product generato si trova all’interno della directory app/. Sebbene la classe del modello possa sembrare vuota, è dotata di vari metodi di creazione di query che è possibile utilizzare per interrogare il database. Ad esempio, puoi utilizzare Product::all()
per recuperare tutti i prodotti o Product::find(1)
per recuperare un particolare prodotto con id 1.
I modelli Laravel hanno un meccanismo di protezione integrato contro la vulnerabilità dell’assegnazione di massa. La proprietà fillable
viene utilizzata per dichiarare i nomi degli attributi che possono essere assegnati in massa in modo sicuro.
1 |
protected $fillable = ['title', 'description', 'price', 'availability'];
|
Il codice sopra elenca gli attributi title
, description
, price
e availability
e li tratta come assegnabili in massa. Infine, esegui il seguente comando per eseguire le migrazioni in sospeso.
1 |
php artisan migrate
|
Questo comando creerà le tabelle predefinite (ad esempio users, migrations) e la tabella che hai definito (products) all’interno del database impesud che abbiamo precedentemente impostato come database dell’applicazione nel file .env.
Ora possiamo utilizzare il metodo Product::create
per inserire nuove righe nella tabella dei prodotti.
Database
Laravel ti consente di popolare il tuo database di sviluppo e produzione con dati fittizi che puoi utilizzare per testare i tuoi endpoint API. Puoi creare una seed class
eseguendo il seguente comando Artisan.
1 |
php artisan make:seeder ProductsTableSeeder
|
I file seeder generati verranno inseriti nella directory database/seeders.
Per generare i dati fittizi, potresti usare qualcosa come str_random(10) che restituisce una stringa casuale. Ma se hai bisogno di dati che siano abbastanza vicini ai dati reali, dovresti usare qualcosa come la libreria faker. Faker è una libreria di terze parti che viene fornita con il framework Laravel per la generazione di dati fake.
Ecco una classe seeder per la generazione di dati seed. Dovrebbe andare in database/seeder/ProductsTableSeeder.php.
Esegui il comando artisan db:seed
per popolare la tabella dei prodotti con dati fake.
1 |
php artisan db:seed --class=ProductsTableSeeder
|
Controller
Il file routes/api.php attualmente ospita la logica per l’instradamento e la gestione delle richieste. Possiamo spostare la logica di gestione delle richieste in una classe Controller in modo che il nostro codice sia meglio organizzato e più leggibile. Generiamo prima una classe controller.
1 |
php artisan make:controller ProductsController
|
La classe Controller comprende vari metodi (index, show, store, update e delete) che corrispondono a diverse azioni HTTP. Ho spostato la logica di gestione delle richieste dal route al controller. Il ProductsController
che abbiamo generato si trova in app/Http/Controllers/ProductsController.php.
Ora aggiorna route/api.php con la nuova importazione e routes.
Se non l’hai notato, ho inserito un’istanza di Product nei metodi del controller. Questo è un esempio dell’associazione implicita di Laravel. Laravel cerca di far corrispondere il nome dell’istanza del modello Product $product
con il nome del segmento URI {product}
. Se viene trovata una corrispondenza, un’istanza del modello Product viene inserita nelle azioni del controller. Se il database non ha un prodotto, restituisce un errore 404.
Apri VS Code e gli endpoint per il prodotto dovrebbero funzionare, prova con http://127.0.0.1:8000/api/products/1/. Assicurati di avere l’intestazione Accept : application/json
abilitata.
Convalida e gestione delle Eccezioni
Se vai su una risorsa inesistente, questo è ciò che vedrai.
NotFoundHTTPException
è il modo in cui Laravel visualizza l’errore 404. Se invece desideri che il server restituisca una risposta JSON, dovrai modificare il comportamento di gestione delle eccezioni predefinito. Laravel ha una classe Handler dedicata alla gestione delle eccezioni che si trova in app/Exceptions/Handler.php. La classe ha principalmente due metodi: report()
e render()
. Il metodo report
è utile per segnalare e registrare eventi di eccezione, mentre il metodo render
viene utilizzato per restituire una risposta quando si verifica un’eccezione. Aggiorna il metodo render
per restituire una risposta JSON:
Laravel ci consente inoltre di convalidare le richieste HTTP in entrata utilizzando una serie di regole di convalida e restituire automaticamente una risposta JSON se la convalida fallisce. La logica per la validazione sarà collocata all’interno del controller. L’oggetto Illuminate\Http\Request
fornisce un metodo validate che possiamo usare per definire le regole di validazione. Aggiungiamo alcuni controlli di convalida al metodo store in app/Http/Controllers/ProductsController.php.
Riepilogo
Ora disponiamo di un’API funzionante per una product listing application. Tuttavia, l’API non dispone di funzionalità di base come l’autenticazione e la limitazione dell’accesso agli utenti non autorizzati. Laravel ha un supporto predefinito per l’autenticazione e la creazione di un’API è relativamente semplice. Ti incoraggio a implementare l’API di autenticazione come esercizio.
Ora che abbiamo finito con il back-end, sposteremo la nostra attenzione sui concetti del front-end. Non perdetevi la seconda parte!