Route::query() e defaults() nei Model di Laravel 13.35
Il team di Laravel ha rilasciato la v13.35.0 con Route::query() per le route HTTP QUERY, un metodo defaults() opt-in per i model Eloquent, array di proprietà nelle fake assertion di queue, bus, event e notification, limiti di memoria percentuali per queue:work, due novità per lo scheduler pensate per configurazioni multi-server e deploy, e altro ancora.
Route::query()
Joel Butcher ha portato Route::query() in Laravel 13. Registra una route per il metodo HTTP QUERY, un metodo safe che trasporta un body nella request, ideale per endpoint di ricerca con filtri troppo grandi per stare in una query string:
Route::query('/products/search', SearchProductsController::class);Laravel 13.19 ha aggiunto Http::query() e gli helper di test query() e queryJson(), ma definire la route richiedeva Route::match(['QUERY'], ...). Ora QUERY è nell'elenco dei verbi del router, quindi anche Route::any() e Route::redirect() lo intercettano.
A differenza della versione integrata per Laravel 14, lascia invariato il contratto Registrar e la protezione CSRF continua a verificare le request QUERY esattamente come quelle POST. Una route QUERY nel gruppo middleware web richiede un token CSRF, oppure una voce nella lista except. Il nostro tutorial su il metodo HTTP QUERY con la ricerca di Scout copre il lato client.
Consulta la #61797 per maggiori dettagli.
defaults() nei Model con HasDefaultAttributes
Wes Hooper ha portato il metodo defaults() dei model da Laravel 14 a Laravel 13 come trait opt-in. defaults() è la versione come metodo della proprietà $attributes, così i valori di default possono arrivare da config, feature flag o dalla data corrente. In Laravel 13 un model deve usare il trait HasDefaultAttributes perché il metodo venga eseguito:
use Illuminate\Database\Eloquent\Concerns\HasDefaultAttributes;\n\nclass Subscription extends Model\n{\nuse HasDefaultAttributes;\n\nprotected function defaults(): array\n{\nreturn [\n'cancelled' => false,\n'trial_days' => Feature::active('extended-trials') ? 30 : 14,\n];\n}\n}Il trait evita che la modifica abbia effetto sui model che hanno già un metodo chiamato defaults(). I valori di defaults() hanno la precedenza su $attributes e sono raw, quindi saltano cast e mutator.
Consulta la #61813 per maggiori dettagli.
Array di proprietà nelle fake assertion
Jack Bayliss ha aggiornato le fake di Queue, Bus, Event e Notification per accettare un array di valori di proprietà attesi dove accettano una callback:
// Prima\nQueue::assertPushed(ProcessPodcast::class, function (ProcessPodcast $job) use ($podcast, $user) {\nreturn $job->podcast->is($podcast)\n&& $job->user->is($user)\n&& $job->status === 'pending';\n});\n\n// Dopo\nQueue::assertPushed(ProcessPodcast::class, [\n'podcast' => $podcast,\n'user' => $user,\n'status' => 'pending',\n]);Ogni valore viene confrontato con uguaglianza stretta, tranne i model Eloquent, che vengono confrontati con is(). Le proprietà devono essere public, dato che la fake le legge dall'esterno dell'oggetto.
Consulta la #61770 per maggiori dettagli.
Limiti di memoria percentuali per queue:work
Jack Bayliss ha anche aggiornato l'opzione --memory di queue:work per accettare una percentuale del memory_limit di PHP, così il limite del worker segue la dimensione del container invece di un numero fisso di megabyte:
php artisan queue:work --memory=60%Con un memory_limit di 512M, il worker si ferma dopo un job una volta raggiunti circa 307 MB. Se memory_limit è -1, cosa comune per la CLI di PHP, la percentuale si risolve in un numero negativo e il worker non si ferma mai per motivi di memoria. Imposta memory_limit per il processo worker se usi una percentuale.
Consulta la #61753 per maggiori dettagli.
Schedule::alwaysOnOneServer()
Uno scheduler in esecuzione su più server o repliche esegue ogni task su ciascuno di essi, a meno che il task non chiami onOneServer(). Una terza PR di Jack Bayliss aggiunge Schedule::alwaysOnOneServer(), che applica onOneServer() a ogni task schedulato:
// AppServiceProvider::boot()\nSchedule::alwaysOnOneServer();Finora l'opzione era avvolgere ogni task in routes/console.php in una chiamata Schedule::onOneServer()->group(). I task closure senza nome vengono saltati, perché onOneServer() ha bisogno di un nome per costruire il lock. Come onOneServer(), richiede un cache store condiviso da tutti i server.
Consulta la #61789 per maggiori dettagli.
Interrompere i comandi schedulati di lunga durata al deploy
php artisan schedule:interrupt interrompe il loop sub-minuto in schedule:run, ma un comando avviato con runInBackground() non lo rilevava mai. cyppe ha modificato l'interrupt per memorizzare un timestamp, allo stesso modo in cui funziona queue:restart, e ha aggiunto Schedule::hasBeenInterruptedSince() così un comando lungo può fermarsi in un punto sicuro:
use Illuminate\Console\Scheduling\Schedule;\n\npublic function handle(Schedule $schedule)\n{\n$startedAt = now();\n\nforeach ($this->batches() as $batch) {\nif ($schedule->hasBeenInterruptedSince($startedAt)) {\nreturn;\n}\n\n$this->process($batch);\n}\n}schedule:run usa lo stesso controllo, quindi un interrupt avvenuto prima nel corso dello stesso minuto non interrompe più una run che inizia dopo.
Consulta la #61764 per maggiori dettagli.
response()->markdown()
Ashot Gharakeshishyan ha aggiunto un metodo markdown() alla response factory, che si abbina al metodo wantsMarkdown() già esistente nella request:
return $request->wantsMarkdown()\n? response()->markdown($post->markdown)\n: view('posts.show', ['post' => $post]);Restituisce una response normale con content type text/markdown e accetta uno status e degli header come response()->make().
Consulta la #61800 per maggiori dettagli.
Creazione lazy della root per i dischi local
Jamie York ha aggiunto un'opzione lazy_root_creation per i dischi local. Per default, l'adapter local di Flysystem crea la directory root nel momento in cui il disco viene costruito. Con l'opzione impostata a true, la directory viene creata alla scrittura del primo file:
'reports' => [\n'driver' => 'local',\n'root' => storage_path('app/reports'),\n'lazy_root_creation' => true,\n],Consulta la #61799 per maggiori dettagli.
Note di rilascio
Qui sotto puoi vedere l'elenco completo delle nuove funzionalità e degli aggiornamenti, oltre al diff tra 13.34.0 e 13.35.0 su GitHub. Le seguenti note di rilascio provengono direttamente dal changelog:
v13.35.0
- [13.x] Consenti alle fake assertion di accettare un array di proprietà di @jackbayliss in #61770
- [13.x] Supporto alle percentuali per queue:work --memory di @jackbayliss in #61753
- [13.x] I comandi schedulati di lunga durata ora rilevano schedule:interrupt di @cyppe in #61764
- [13.x] Rendi tolleranti a un'esecuzione concorrente le callback parallele delle view compilate di @joshdaugherty in #61786
- [13.x] Aggiungi il metodo markdown() alla response factory di @Ashot1995 in #61800
- [13.x] Aggiungi
onOneServerall'output dischedule:list --jsondi @MizouziE in #61798 - [13.x] Aggiungi l'opzione di configurazione
lazy_root_creationper i dischilocaldi @ziadoz in #61799 - [13.x] Miglioramenti ai test di @crynobone in #61790
- Miglioramenti alle eccezioni di @timacdonald in #61791
- [13.x] Aggiungi Schedule::alwaysOnOneServer(); di @jackbayliss in #61789
- [13.x] aggiungi test per notifyJobOfSignal SIGALRM di @jackbayliss in #61787
- [13.x] Ottimizza Str::finish e Str::start di @HamidRezaLS in #61803
- [13.x] Correggi il ciclo di riferimenti dalla callback di default di PendingRequest::throw() di @andrewnabors in #61802
- [13.x] Correggi isLocked() del lock Memcached su un lock libero di @mrjavadseydi in #61801
- [13.x] Aggiungi il supporto al metodo di route QUERY di @joelbutcher in #61797
- [13.x] Correggi where() e whereNot() di DatabaseRule che perdevano i valori false di @sajjadhossainshohag in #61796
- [13.x] Correggi gli helper di durata che troncavano i valori float di @xurshudyan in #61825
- [13.x] Rilascia i lock dei job unici in
Queue::fakeFor()di @xurshudyan in #61824 - [13.x] Correggi
forceCreate()che ignoravawithAttributes()di @xurshudyan in #61823 - [13.x] Correggi
has()ewithCount()sulle relazioni one-of-many diHasOneThroughdi @xurshudyan in #61818 - [13.x] Accetta una password null in hashPasswordForCookie di @troioi-vn in #61817
- [13.x] Correggi
chunkById()elazyById()che andavano in loop infinito su model con chiave primaria castata di @xurshudyan in #61816 - [13.x] Correggi il MorphPivot personalizzato che non aggiornava i proprietari al detach di @mrjavadseydi in #61812
- [13.x] Correggi collapse(), collapseWithKeys() e flatten() che scartavano le lazy collection di @ahmadreza-fatemikia in #61811
- [13.x] Correggi DB::setDefaultConnection() che memorizzava enum nella configurazione di @ahmadreza-fatemikia in #61810
- [13.x] normalizza la queue nel metodo bulk di SQS di @jackbayliss in #61828
- [13.x] Correggi
HasOneThrough::is()che confrontava le chiavi sbagliate di @xurshudyan in #61827 - [13.x] Correggi gli attributi di queue ereditati che venivano ignorati quando la classe figlia usa Queueable di @xurshudyan in #61826
- [13.x] Correggi gli aggiornamenti dei path JSON su
AsEncryptedArrayObjecteAsEncryptedCollectiondi @xurshudyan in #61834 - Correggi il matching della route root con la route cache quando servita da una sottodirectory di @Simon0Harms in #61794
- Risolvi problemi di query di @taylorotwell in #61837
- [13.x] Documenta il supporto agli enum per il disco in
copyToDisk()emoveToDisk()di @riesjart in #61867 - [13.x] Salta la costruzione di una query in loadMissing() quando non vengono fornite relazioni di @MAboyadak in #61869
- [13.x] Accetta enum in
FilesystemManager::set(),forgetDisk()epurge()di @riesjart in #61868 - [13.x] Correggi il testing parallelo con PHPUnit 13.4 di @lazerg in #61859
- [13.x] Correggi gli attributi di
AsHtmlStringche serializzavano in un oggetto vuoto di @xurshudyan in #61854 - [13.x] Correggi
whereJsonOverlaps()con un path JSON su MySQL di @xurshudyan in #61853 - [13.x] Correggi il ciclo di riferimenti dalle callback headers() e priority() di Mailable di @xurshudyan in #61863
- [13.x] Correggi
findOrNew()echunkMap()su HasManyThrough e BelongsToMany di @xurshudyan in #61855 - [13.x] Correggi
incrementOrCreate()che non impostava la chiave esterna sulle relazioni di @xurshudyan in #61849 - [13.x] Correggi
loadMissing()con relazioni annidate su modelmorphTomisti di @xurshudyan in #61845 - [13.x] Correggi findOrFail() di Eloquent Collection con una collection di id di @xurshudyan in #61844
- [13.x] Correggi
cursorPaginate()che perdeva i binding di union select e join di @xurshudyan in #61841 - [13.x] Correggi i docblock del metodo
logoutOtherDevicesdi @imanghafoori1 in #61877 - [13.x] Correggi gli aggiornamenti dei path JSON che scartavano le modifiche non salvate sugli oggetti castati di @xurshudyan in #61847
- [13.x ] tipo di ritorno
neverper il metodofailedBasicResponsedi @imanghafoori1 in #61887 - [13.x] Correggi i download che andavano in crash con nomi file senza equivalente ASCII di @jhm-ciberman in #61888
- [13.x] Qualifica le colonne eager loaded nelle relazioni through e one-of-many di @xurshudyan in #61885
- [13.x] Correggi i model riciclati che si propagavano nelle chiamate successive sulla stessa factory di @xurshudyan in #61884
- [13.x] Fai il fake dell'API pwnedpasswords in ValidationPasswordRuleTest::testMessagesOrder di @xurshudyan in #61880
- [13.x] Correggi
morphTo()->withTrashed()che veniva ignorato dahas()ewhereHasMorph()di @xurshudyan in #61846 - [13.x] Correggi
incrementOrCreate()che ignorava gli attributi extra in fase di creazione di @xurshudyan in #61878 - [13.x] Correggi la chiave di array non definita in GenericUser::getAuthPassword() per gli utenti senza password di @tommie1001 in #61876
- [13.x] Miglioramenti ai test del database di @jnoordsij in #61819
- [13.x] Porta
defaults()tramite trait opt-in di @weshooper in #61813 - Aggiorna source-map-js da 1.2.1 a 1.2.2 in /src/Illuminate/Foundation/resources/exceptions/renderer di @dependabot in #61889
- [13.x] Correggi la conversione di timezone di
schedule:listquando le esecuzioni successive attraversano un cambio di ora legale di @xiCO2k in #61894 - [13.x] Non espandere i template URL senza parametri URL di @xurshudyan in #61893
- [13.x] Ignora _token e _method quando si fallisce su campi sconosciuti di @xurshudyan in #61891
- [13.x] Correggi
withCasts()su una query clonata che modificava i cast della query originale di @xurshudyan in #61883
Fonte originale:
https://laravel-news.com/laravel-13-35-0Altri articoli recenti
Laravel AI 1.1 e 1.2: Agent Skills, Cohere e structured output più solidi
Le release 1.1.0 e 1.2.0 di laravel/ai portano gli Agent Skills, l'approvazione obbligatoria per i tool built-in e nuovi provider come Cohere e Laya self-hosted. Sul fronte qualità arrivano i fix allo structured output per Bedrock e il supporto alle provider options. Aggiornati anche i modelli di default, con Claude 4.7+ che ignora i sampling params.
Laravel 13.35.0: scheduler più controllabile, code più flessibili e response Markdown
Laravel 13.35.0 porta Schedule::alwaysOnOneServer(), il supporto a schedule:interrupt per i comandi di lunga durata, --memory in percentuale per queue:work e il nuovo metodo markdown() sulla response factory. Tante piccole migliorie anche a test, view compilate in parallelo e dischi local.
BashBox: un interprete Bash in sandbox per agenti AI in PHP
BashBox è un interprete bash scritto in puro PHP che permette di eseguire gli script generati dagli agenti AI senza mai ricorrere a proc_open, exec o shell_exec. Ogni comando è una classe PHP che lavora su un filesystem virtuale, con limiti di esecuzione, quote disco e accesso di rete configurabili. Ideale per chi sviluppa agenti con il Laravel AI SDK o altre librerie simili.