Il framework Laravel è ormai un’istituzione per gli sviluppatori php o aspiranti tali. Laravel si basa, infatti, proprio sul linguaggio PHP e fornisce tutti gli strumenti necessari per semplificare la vita degli sviluppatori. Oltre ad un elevato tasso di personalizzazione ed efficienza, Laravel si rivela una risorsa utile anche per chi vuole imparare PHP ed iniziare a costruirsi della basi nel mondo della programmazione informatica. In questo articolo vedremo cosa sono i DTO in Laravel e come implementarli.
Che cosa sono i DTO
Ti sei mai chiesto perché, quando scrivi un controller in Laravel, a volte può essere ricco di tante istruzioni condizionali e operatori logici? Ciò rende la manutenzione del progetto dispendiosa e difficile in previsione futura.
Ottimizzare il codice non vuol dire soltanto renderlo più leggibile, ma anche più facile da manutenere e renderlo più performante sotto l’aspetto back-end. Vediamo insieme alcune strategie per semplificare la scrittura di un controller e separare le varie logiche per renderlo più modulare.
Una delle soluzioni a questo problema è l‘uso dei DTO (Data Transfer Object).
I DTO sono oggetti semplici utilizzati per trasferire dati tra diverse parti di un’applicazione senza includere logiche di business complesse. In pratica, un DTO è una classe che contiene solo attributi e metodi getter e setter, senza metodi che manipolino direttamente i dati o eseguano operazioni di logica.
Utilizzando i DTO, puoi ridurre significativamente la complessità dei controller perché i DTO permettono di gestire i dati in modo centralizzato e coerente. Questo approccio non solo migliora la leggibilità del codice, ma anche la sua manutenibilità. Invece di avere molteplici controlli e trasformazioni dei dati sparsi nei controller, puoi centralizzare queste operazioni nei DTO, rendendo il codice più modulare e facile da testare.
Imparare PHP attraverso i DTO
La prima cosa da fare è lasciare la validazione fuori dal controller e spostarla in una richiesta di form. Per creare una classe di richiesta di form, si può usare il comando php artisan make:request Artisan:
php artisan make:request StoreArticleRequest
Con la seguente istruzione creeremo un nuovo file in app/Http/Requests/StoreArticleRequest.php
Ogni richiesta sarà sempre autorizzata, quindi avremo una classe strutturata in questo modo:
class StoreArticleRequest extends FormRequest 2. { 3. /** 4. * Determina se l’utente è autorizzato a fare questa richiesta. 5. * 6. * @return bool 7. */ 8. public function authorize() 9. { 10. return true; 11. } 12. /** 13. * Ottenere le regole di validazione che si applicano alla richiesta. 14. * 15. * @return array<string, mixed> 16. */ 17. public function rules() 18. { 19. return [ 20. 'title' => ['required', 'min: 6', 'max: 255', 'unique: articles, title'], 21. 'content' =>['required'], 22. 'category_id' => ['required'], 23. 'cover' => ['required'], 24. 'status' = => ['required'], 25. ]; 26. } 27. }
Ora, aggiorniamo il nostro controllore, rimuovendo la validazione nel controllore e utilizzando StoreArticleRequest, in modo che la richiesta sia gestita da StoreArticleRequest prima di arrivare al controllore.
1. public function store (StoreArticleRequest $request) 2. { 3. $path $request->file('cover')->store('covers'); 4. } 5. $article = Article::create ([ 6. 'title' => $request->title, 7. 'content' => $request->content, 8. ]); 9. 'category_id' => $request->category_id, 10. 'cover' => $path, 11. 'status' => $request->status, 12. if ($article->status 1) { 13. $this->dispatch (BroadcastNewArticle::class); 14. } 15. return redirect ( )->route('article.index')->with('success' 16. 'Article has been stored');
Il passo successivo consiste nello spostare la logica comune in una ‘action’ o in una ‘service class’. Useremo una classe azione perché ci servirà per l’implementazione del DTO nella fase conclusiva.
<?php 2. namespace App\Actions; 3. use App\Models\Article; 4. use Illuminate\Http\Request; 5. class AulabArticlesAction 6. { 7. public function execute (Request $request) : Article 8. 9. { 10. 11. if($request->cover != null) { 12. $path = $request->file('cover')->store('covers'); 13. } 14. 15. $article = Article::create( [ 16. 'title' => $request->title, 17. 'content' => $request->content, 18. 'category_id' => $request->category_id, 19. 'cover' => $path ?? null, 20. 'status' => $request->status, 21. ]); 21. return $article; 22. 23. } 24. }
L’Action verrà richiamata nella classe creata in precedenza in modo tale da rendere modulare la gestione degli operatori logici e rendere il controller molto più leggibile.
L’implementazione dei DTO in Laravel
Cosa succede se si dispone di un’API per memorizzare un articolo che accetta campi diversi da quelli presenti nell’StoreArticleAction, ad esempio nella richiesta API cambia il nome della colonna da title a title_temp? Ma i requisiti tecnici obbligano a usare la stessa nel StoreArticleAction sia nelle richieste web che in quelle API.
Possiamo risolvere questo problema utilizzando i DTO (data transfer object). Per utilizzare i DTO nel nostro progetto, useremo il pacchetto Spatie/data-transfer-object. Per installare il pacchetto, utilizzare il seguente comando:
composer require spatie/data-transfer-object
Dopodichè creeremo un file chiamato ArticleStoreDTO che avrà all’interno una funzione per richiamare la richiesta ad AluabArticlesRequest tramite una funzione ToDTO().
. <?php 2. namespace App\DataTransfer0bjects; 3. use Illuminate\Http\UploadedFile; 4. use Spatie\DataTransferObject\DataTransferObject; 5. class ArticleStoreDTO extends DataTransferObject 6. { 7. 8. public string $title; 9. public string $content; 10. public int $category_id; 11. public UploadedFile $cover; 12. public string $status; 13. }
Infine, modificheremo StoreArticleAction per accettare il DTO appena creato.
1. class ArticleStoreAction { 2. public function execute( 3. ArticleStoreDTO $articleStoreDTO 4. ): Article 5. { 6. if ($articleStoreDTO->cover != null) { 7. $path = $articleStoreDTO->cover->store('covers'); 8. } 9. 10. 11. $article = Article::create([ 12. 'title' => $articleStoreDTO->title, 13. 'content' => $articleStoreDTO->content, 14. 'category_id' => $articleStoreDTO->category_id, 15. 'cover' => $path ?? null, 16. 'status' => $articleStoreDTO->status, 17. ]); 18. return $article; 19. }}
Come si può vedere nel codice qui sopra, imposteremo il valore per il nostro record che proviene dai DTO.
Ora torniamo al problema precedente: come si fa a implementare StoreArticleAction alla richiesta API che ha un nome di colonna diverso da title_temp?
È molto semplice, ci sono molti modi per farlo, uno di questi è creare una nuova richiesta e assegnare il campo title_temp al campo content del DTO.
Finché il StoreArticleAction accetta dati validi da DTO, tutto andrà bene.
Queste sono tecniche molto utili per disaccoppiare i dati, in modo che possano essere inviati attraverso il codice del sistema senza essere legati a nulla (in questo caso, alla richiesta).
Ora è possibile utilizzare questa logica in molti punti, senza dover duplicare il codice, il che rappresenta un altro fantastico vantaggio dell’isolamento della logica aziendale in servizi o classi di azioni.
Conclusione
Questa pratica è molto utilizzata tra gli sviluppatori PHP, inoltre, se vuoi imparare PHP ti consigliamo di assimilarne i concetti e cercare di farla propria per accrescere il bagaglio che si vuole ottenere per aspirare a diventare un web developer utilizzando Laravel. Laravel ti appassiona? Puoi trovare sul nostro sito la guida a Laravel in italiano!