In questo approfondimento imparerai come creare una To-Do List utilizzando:
- Il framework PHP Laravel;
- La libreria CSS NES.CSS;
- SqlLite come Database
Vedrai come utilizzare Laravel per creare una To-Do List funzionale e ben progettata.
Crea il progetto Laravel
Per prima cosa, crea un nuovo progetto Laravel utilizzando la guida subito qui riportata:
Guida su come installare Laravel su Windows e Mac
Per comodità, supponiamo tu abbia scelto l’installazione via Laravel Installer (Metodo Raccomandato se sei alle prime armi!).
Lancia i comandi nel terminale:
laravel new todolistcd todolistphp artisan serve
Comparirà nel terminale l’indirizzo relativo per accedere al progetto.
Digitando l’url presente nel terminale, potrai accedere alla starter page di Laravel:
http://127.0.0.1:8000
Configura il file di ambiente .env
Per fini accademici utilizzeremo SQLITE, molto più leggero di MySQL e di facile inizializzazione.
Apri il file .env del progetto e modifica le impostazioni di connessione al DB cancellando tutte le altre configurazione DB_ come segue:
DB_CONNECTION=sqlite
Infine lancia il comando per creare fisicamente il DB:
php artisan migrate
Crea le tabelle con le Migration
Per creare le tabelle, lancia il comando:
php artisan make:migration create_tasks_table
Verrà generata la migrations in: database/migrations
Aprendo il file appena generato, aggiungi la stringa relativa alla description, in questo modo:
public function up(){ Schema::create('tasks', function (Blueprint $table) { $table->id(); $table->string('description'); $table->timestamps(); });}
Ancora, lancia il comando per creare fisicamente la tabella nel DB:
php artisan migrate
Definisci i Model
Hai creato fisicamente le tabella, ma Laravel non sa ancora come interagirci, necessita di un collegamento logico.
Lancia il comando:
php artisan make:model Task
Verrà creato un nuovo file in: app/Models/Task.php
ATTENZIONE!
Per utilizzare l’aggiornamento massivo, dovrai abilitare manualmente i campi in questo modo:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Task extends Model { protected $fillable = [ 'description' ]; }
Definiamo le rotte dell’applicazione
Come ogni buon navigatore che si rispetti, prima di partire è necessario progettare tutte le strade e rotte da percorrere nell’avventura.
Avremo bisogno di:
- Una rotta con un form di inserimento Task e tutti i Task già inseriti (INDEX);
- Una rotta a cui mandare i dati in post, validarli e scriverli nel database(STORE);
- Una rotta a cui mandare l’identificativo della risorsa e cancellarlo (DESTROY).
Apri quindi il file routes/web.php
e sostituisci il contenuto con queste tre righe:
<?php use Illuminate\Support\Facades\Route; Route::get('/', [TasksController::class, 'index'])->name('tasks.index');Route::post('/tasks', [TasksController::class, 'store'])->name('tasks.store');Route::delete('/tasks/{id}', [TasksController::class, 'destroy'])->name('tasks.destroy');
Occupiamoci della logica con i Controller
Da terminale lancia il comando:
php artisan make:controller TaskController
Verrà creato un nuovo file e posizionato in:
app/Http/Controllers/TaskController.php
Le operazioni (quindi le funzioni) che andrai a sviluppare sono:
- index(): La funzione per visualizzare la schermata principale;
- store(): La funzione che verrà richiamata ogni qualvolta si dovrà memorizzare un dato;
- destroy(): La funzione che verrà richiamata ogni qualvolta si dovrà cancellare un dato;
Metodo index
Avremo bisogno di un metodo indice in cui richiamare tutti i Task inseriti nel Database e visualizzarli in una view di elenco.
Copia e incolla il codice qui sotto nel tuo controller, assicurandoti di sovrascrivere tutto il contenuto precedente:
<?php namespace App\Http\Controllers; use App\Models\Task;use Illuminate\Http\Request; class TaskController extends Controller{ public function index() { $tasks = Task::latest()->get(); return view('tasks', compact('tasks')); }}
Metodo store
La visualizzazione è fatta, non ci resta che implementare la memorizzazione dei Task.
Importeremo la classe Request per gestire i dati che passeranno in POST e andremo a definire una piccolissima regola di validazione per gestire correttamente le attività:
<?php namespace App\Http\Controllers; use App\Models\Task;use Illuminate\Http\Request; class TaskController extends Controller{ public function index() { $tasks = Task::latest()->get(); return view('tasks', compact('tasks')); } public function store(Request $request) { Task::create($request->validate( [ 'description' => ['required', 'string', 'max:255'] ] )); return to_route('tasks.index'); }}
Metodo destroy
E come ultima operazione non ci resta che inserire la cancellazione dell’attività una volta completata.
<?php namespace App\Http\Controllers; use App\Models\Task;use Illuminate\Http\Request; class TaskController extends Controller{ public function index() { $tasks = Task::latest()->get(); return view('tasks', compact('tasks')); } public function store(Request $request) { Task::create($request->validate( [ 'description' => ['required', 'string', 'max:255'] ] )); return to_route('tasks.index'); } public function destroy($id) { $task = Task::findOrFail($id); $task->delete(); return to_route('tasks.index'); }}
Interfaccia grafica con Nes.css
Adesso proviamo ad utilizzare la libreria Nes.css. Cerca e rinomina la view che puoi trovare in:
resources/views/welcome.blade.php
In una più consona:
resources/views/tasks.blade.php
L’obiettivo sarà quello di utilizzare le classi css già esistenti e creare due situazioni:
Nessun task inserito:
Ci sono dei task inseriti:
Per pigrizia ho inserito tutto in un unico file blade, puoi utilizzare questa view:
<!DOCTYPE html><html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>To Do List</title> <link href="https://unpkg.com/nes.css@latest/css/nes.min.css" rel="stylesheet" /> <style> @font-face { font-family: 'Press Start 2P'; font-style: normal; font-weight: 400; src: local('Press Start 2P Regular'), local('PressStart2P-Regular'), url('https://fonts.gstatic.com/s/pressstart2p/v8/e3t4euO8T-267oIAQAu6jDQyK3nVivNm4I81.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } body { width: 100%; min-height: 100vh; font-family: 'Press Start 2P', cursive; display: flex; flex-direction: column; justify-content: center; align-items: center; } .my-3 { margin-bottom: 3rem; margin-top: 3rem; } .container { max-width: 720px; margin: 0 auto; padding-left: 1rem; padding-right: 1rem; } .w-full { width: 100%; } </style></head> <body class="container"> <div class="nes-container with-title is-centered w-full"> <p>Devo ricordarmi di...</p> <form method="POST" class="nes-field is-inline" action="{{ route('tasks.store')}}"> @csrf <input type="text" id="description" name="description" class="@error('description') is-error @enderror nes-input"> <button type="submit" class="nes-btn is-primary">+</button> </form> @error('description') <span class="nes-text is-error"> <span>{{ $message }}</span> </span> @enderror </div> @forelse($tasks as $task) <div class="nes-container with-title is-centered my-3 w-full"> <p class="title">Attività {{$loop->remaining + 1}}</p> <form action="{{ route('tasks.destroy',$task->id) }}" method="POST"> <div class="is-inline flex justify-between items-center max-w-md"> <p class="pr-4">{{$task->description}}</p> @csrf @method('DELETE') <button type="submit" class="nes-btn is-success ml-1 h-12">Fatto </button> </div> </form> </div> @empty <div class="nes-container is-centered my-3 w-full"> <p>Ti stai annoiando? Inserisci qualche Tasks!</p> <i class="nes-icon coin is-medium"></i> <i class="nes-icon coin is-medium"></i> <i class="nes-icon coin is-medium"></i> <i class="nes-icon coin is-medium"></i> <i class="nes-icon coin is-medium"></i> </div> @endforelse</body> </html>