Sviluppo Laravel
Applicazioni Laravel, sviluppate e mantenute in funzione.
Dal primo modello ai worker delle code, dai rilasci all'aggiornamento di anni dopo: scritte, ospitate e seguite da un unico team.
Un rilascio, così come appare sul server
Ogni applicazione Laravel che gestiamo va online allo stesso modo: testata, preparata, messa in cache e attivata senza un secondo di interruzione.
01ci ~/app $ php artisan test PASS Tests\Feature\CheckoutTest ✓ a paid order queues the invoice ✓ a declined card never marks the order paid PASS Tests\Unit\VatTest ✓ vat is added once, on the total 02app ~/releases/1400 $ composer install --no-dev --optimize-autoloaderInstalling dependencies from lock fileGenerating optimized autoload files 03app ~/releases/1400 $ php artisan migrate --force INFO Running migrations. 2026_09_27_090000_add_due_date_to_invoices ....... DONE 04app ~/releases/1400 $ php artisan optimize INFO Caching framework bootstrap, configuration, and metadata. config ...................................... DONE events ...................................... DONE routes ...................................... DONE views ....................................... DONE 05app ~/releases/1400 $ ln -sfn ~/releases/1400 ~/current06app ~/releases/1400 $ php artisan horizon:terminate && php artisan octane:reload 07app ~/releases/1400 $ sudo supervisorctl statushorizon RUNNING pid 48211, uptime 0:00:09octane RUNNING pid 31877, uptime 6 days, 2:14:51 08app ~/releases/1400 $ php artisan schedule:list */5 * * * * php artisan horizon:snapshot ... Next Due: 3 minutes from now 0 2 * * * php artisan model:prune ........ Next Due: 9 hours from now 0 9 * * * php artisan invoices:remind .... Next Due: 16 hours from now
Prima i test
I test girano prima che qualsiasi cosa arrivi al server. Un solo test fallito blocca il rilascio.
Dipendenze
Installate solo dal file di lock, senza pacchetti di sviluppo, con un autoloader ottimizzato.
Migrazioni
Scritte in modo che il codice in esecuzione continui a funzionare con il nuovo schema durante il passaggio al nuovo rilascio.
Cache
Configurazione, eventi, rotte e viste vengono messi in cache. Da qui in poi il file d'ambiente non viene più letto, ed è per questo che env() va usato solo nei file di configurazione.
Il cambio
Un link si sposta e il nuovo rilascio è online. Quello precedente resta su disco per un eventuale rollback.
Worker
Horizon completa i job in corso e riparte con il nuovo codice; Octane ricarica i suoi worker allo stesso modo.
Supervisionati
Supervisor mantiene in esecuzione Horizon e Octane, e riavvia l'uno o l'altro se si ferma.
Lo scheduler
Una sola riga di cron esegue ogni attività pianificata. Ecco la prossima che eseguirà.
Da un clic a un job completato
Il lavoro lento esce dalla richiesta. Il cliente riceve subito una risposta e un worker fa il resto in background.
-
01 · Richiesta
POST /checkoutIl cliente paga
Il controller convalida l'ordine, lo salva e risponde subito. Qui non avviene nulla di lento.
-
02 · Job
PayOrder::dispatch()La parte lenta diventa un job
Inviato dopo il commit del database, così un worker non prende mai in carico un ordine annullato da un rollback.
-
03 · Coda
redis · paymentsAspetta nella sua coda
I pagamenti hanno una coda tutta loro, così un'esportazione lunga non ne blocca mai uno.
-
04 · Worker
horizon · supervisorUn worker lo prende in carico
Con un timeout, nuovi tentativi che attendono ogni volta più a lungo e un limite a quanti ne girano contemporaneamente.
-
05 · Notifica
OrderPaid → mail, databaseTutti vengono avvisati
Il cliente riceve la fattura via email e l'ordine risulta pagato nella tua dashboard.
failed_jobs
Un job che esaurisce i tentativi viene conservato con il suo errore e noi riceviamo un avviso. Viene rieseguito una volta risolta la causa: mai perso in silenzio.
L'intera applicazione, non solo il server
Il nostro team porta venticinque anni di esperienza in PHP in ogni progetto Laravel, dal primo modello all'aggiornamento di anni dopo.
Sviluppare
L'applicazione in sé.
- Architettura
- Logica di business in azioni e servizi, non nei controller. Form request per la validazione, policy per stabilire chi può fare cosa.
- Eloquent
- Relazioni caricate in anticipo dove una pagina le elenca, così una pagina costa poche query e non centinaia. In sviluppo il lazy loading genera un errore, così il problema emerge subito.
- Livewire · Inertia
- Livewire quando il team scrive PHP e Blade; Inertia con Vue o React quando il front end è un progetto a sé.
- API con Sanctum
- Token per app mobili e partner, sessioni con cookie per il tuo front end e limiti di richieste per ogni client.
- Pest · PHPUnit
- Test per ogni percorso che incassa denaro o invia email, eseguiti a ogni push prima che venga preparato un rilascio.
Gestire
Ciò che la mantiene reattiva.
- Code e Horizon
- Code separate per il lavoro urgente e per quello massivo, ognuna con i propri worker, timeout e tentativi, monitorate nella dashboard di Horizon.
- Lo scheduler
- Una sola riga di cron esegue ogni attività. Le attività che non devono sovrapporsi, o che devono girare su un solo server, sono contrassegnate come tali.
- Octane
- Swoole, RoadRunner o FrankenPHP tengono l'applicazione in memoria tra una richiesta e l'altra. Prima di attivarlo, controlliamo che nel codice non ci sia stato che passa da una richiesta alla successiva.
- Redis
- Cache, sessioni, code e lock, su un Redis non raggiungibile da internet.
- Supervisor
- Worker delle code, Horizon e Octane girano come processi supervisionati, riavviati se si fermano e dopo ogni rilascio.
Mantenere
Ciò che la mantiene aggiornata.
- Rilasci senza interruzioni
- Ogni rilascio viene preparato in una propria directory e attivato con un solo link. Tornare indietro è lo stesso passaggio al contrario.
- Log ed eccezioni
- File di log giornalieri conservati per un periodo stabilito, e ogni eccezione segnalata a noi insieme alla richiesta che l'ha causata.
- Aggiornamenti di versione
- Laravel pubblica una versione major ogni anno. Portiamo avanti un'applicazione una versione alla volta, con i test superati a ogni passaggio.
Cosa configuriamo fin dal primo giorno
Prima che arrivi il primo cliente, ogni server Laravel che gestiamo ha già tutto questo al suo posto.
- Modalità debug disattivata in produzione e solo la directory pubblica esposta sul web
APP_DEBUG=false - Worker delle code sotto Supervisor, riavviati a ogni rilascio
supervisord - Una sola riga di cron per lo scheduler
* * * * * php artisan schedule:run - Redis per cache, sessioni e code
CACHE_STORE=redis - Configurazione, eventi, rotte e viste in cache a ogni rilascio
php artisan optimize - OPcache attivo e azzerato a ogni rilascio
opcache.validate_timestamps=0 - Un pool PHP-FPM dimensionato sulla memoria del server
pm.max_children - Rilasci in directory separate, a un passo dal rollback
current → releases/… - Job falliti segnalati a noi, non lasciati in una tabella
failed_jobs - Rotazione dei log e avvisi sulle eccezioni
LOG_CHANNEL=daily - Un backup notturno del database, copiato fuori dal server
backup · offsite - Un certificato TLS che si rinnova da solo
Let's Encrypt
Un rilascio su disco
/var/www/example-app
├── current → releases/1400
├── releases/
│ ├── 1400
│ └── 0930
└── shared/
├── .env
└── storage/

Raccontaci la tua applicazione
Un nuovo sviluppo, un'applicazione che cerca casa o una ferma a una vecchia versione. Ogni progetto viene preventivato dopo una breve conversazione.