Laravel 13.27 est sorti le 26 août 2026 avec un mélange de durcissements de sécurité et de nouvelles API du query builder.

Le changement phare est mask_bindings_in_exception_messages, une clé de configuration par connexion. QueryException interpole normalement les bindings dans son message, donc un insert en échec place des valeurs comme des adresses e-mail dans getMessage(), qui se retrouvent ensuite dans la table failed_jobs, les logs et les spans APM. Avec l'option activée, le message conserve les marqueurs ? tandis que getBindings() renvoie toujours les valeurs. La clé est livrée dans le config/database.php du framework, donc les applications qui n'ont jamais publié ce fichier peuvent l'activer avec DB_MASK_BINDINGS=true. Valeur par défaut : false. Contribution de @LauJosefsen dans la PR #61326.

Les nouvelles méthodes whereBinary(), orWhereBinary(), whereNotBinary() et orWhereNotBinary() apportent des comparaisons exactes à l'octet au query builder. Les collations par défaut de MySQL comparent sans tenir compte de la casse, donc where('name', 'John') correspond aussi à john ; il fallait auparavant passer par whereRaw('name = BINARY ?', ...). MariaDB hérite de la grammaire MySQL et fonctionne également, tandis que Postgres, SQLite et SQL Server lèvent une RuntimeException, comme whereLike(). Contribution de @xiCO2k dans la PR #61261.

refreshForUpdate() recharge un modèle Eloquent sur place avec lockForUpdate() appliqué. Les modèles sont généralement résolus avant le début d'une transaction, via le route model binding ou un payload de job, donc prendre un verrou pessimiste imposait de jeter l'instance et de re-requêter par clé primaire. Le verrou ne dure que le temps de la transaction, l'appel doit donc s'y trouver, et il ferme la course de données entre la lecture du modèle et sa réécriture. Contribution de @stevebauman dans la PR #61247.

Une nouvelle facade Cloud répond à la question "sommes-nous sur Laravel Cloud ?" avec trois méthodes : Cloud::hosted(), Cloud::usesManagedQueues() et Cloud::queue(). Cette dernière lève une RuntimeException si les queues managées ne sont pas configurées. La facade n'est volontairement pas enregistrée dans les alias par défaut pour éviter les collisions avec des classes Cloud existantes, et l'ancienne classe de bootstrap a été renommée CloudBootstrapper. Contribution de @jackbayliss dans la PR #61275.

Les queues gagnent Queue::totalPendingSize(), totalDelayedSize() et totalReservedSize(), qui additionnent toutes les files connues d'une connexion sans décoder les payloads des jobs. Implémenté pour les pilotes Redis, database, failover et fake (PR #61231).

Les requêtes de distance vectorielle fonctionnent désormais sous MariaDB. whereVectorSimilarTo(), whereVectorDistanceLessThan(), orderByVectorDistance() et selectVectorDistance() étaient réservées à Postgres car la vérification était un instanceof PostgresConnection avec l'opérateur pgvector <=> codé en dur. Les deux ont migré vers la grammaire, et MariaDB 11.7+ compile vers vec_distance_cosine(). MySQL simple lève toujours une exception, VECTOR_DISTANCE() n'existant que sur MySQL HeatWave (PR #61250).

La gestion des entrées et la validation ont reçu plusieurs durcissements de @KIKOmanasijev. Request::merge(['*' => 226]) vidait auparavant tout le tableau d'entrée car les clés passaient par data_set(), qui traite * comme un joker ; Uri::withQuery() avait le même bug. Les deux utilisent désormais Arr::set() (#61309, #61312). Le rejet des champs inconnus aplatissait l'entrée avec Arr::dot(), donc une clé littérale "profile.name" contournait le contrôle sans qu'aucune règle ne la valide ; les clés d'entrée utilisent maintenant le même échappement que les clés de règles (#61313). Les règles in_array et doesnt_contain comparent désormais strictement, ce qui met fin aux faux positifs comme "1e0" contre "1" (#61319, #61318), et MaintenanceModeBypassCookie::isValid() vérifie is_string() au lieu d'isset(), donc un cookie contenant un tableau ne transforme plus un 503 attendu en 500 non authentifié (#61314).

Points mineurs : les connexions Postgres acceptent les options DSN keepalives, keepalives_idle, keepalives_interval et keepalives_count, afin que les pare-feux ne tuent plus silencieusement les connexions de workers longue durée (#61307). SQS peut partager un cache d'identifiants AWS entre processus via une option credentials_cache, activée par défaut pour les queues managées de Laravel Cloud (#61321). orWhereKey() et orWhereKeyNot() sont de retour après le revert de la tentative de la 13.26 qui cassait les sous-classes de Builder ; la nouvelle version délègue via un groupe where imbriqué (#61242). move() et copy() sur un disque read-through streament désormais depuis le fallback quand le primaire n'a pas encore promu le fichier (#61272). Les jobs débouncés ne laissent plus traîner leur timestamp maxWait (#61281), les closures de contraintes d'eager loading sont à nouveau statiques, brisant un cycle de références qui gardait les builders en vie dans les workers et Octane (#61264), et InteractsWithTestCaseLifecycle::flushState() offre un hook documenté pour nettoyer l'état statique entre les tests (#61288).