Une application Laravel peut s'arrêter sur l'erreur SQLSTATE[HY000]: General error: 1615 Prepared statement needs to be re-prepared, souvent lors d'une suppression ou d'une modification de données. MySQL signale qu'une requête préparée doit être préparée à nouveau, parce que les informations qu'il garde en mémoire sur une table ont changé entre la préparation et l'exécution. Ce cache est commun à tout le serveur et ne peut pas être agrandi pour un seul hébergement. La correction se fait donc dans votre application : demander à PDO d'émuler les requêtes préparées côté PHP.
En bref : ajoutez la ligne PDO::ATTR_EMULATE_PREPARES => true, dans les 'options' du bloc mysql de config/database.php, puis lancez php artisan config:cache si la configuration est en cache. N'utilisez pas Pdo\Mysql:: avant PHP 8.4.
Prérequis
- Un accès aux fichiers de votre application Laravel, par FTP ou en SSH.
- Une base de données MySQL utilisée avec le pilote
mysql de Laravel.
Ce qu'il faut savoir avant de commencer
- N'ajoutez qu'une ligne. Ne remplacez pas tout le bloc
mysql de votre configuration par un exemple trouvé en ligne : vous perdriez vos propres réglages.
- Écrivez
PDO::ATTR_EMULATE_PREPARES, pas Pdo\Mysql::ATTR_EMULATE_PREPARES. La classe Pdo\Mysql n'existe qu'à partir de PHP 8.4. Sur PHP 8.3 ou antérieur, la ligne provoque une erreur fatale (Class "Pdo\Mysql" not found). PDO::ATTR_EMULATE_PREPARES fonctionne sur toutes les versions de PHP proposées dans la console Apanel.
- La protection contre les injections SQL reste active. Avec l'émulation, PDO échappe lui-même les valeurs liées par Laravel (Eloquent, Query Builder, paramètres
?). Gardez le jeu de caractères utf8mb4 de la configuration Laravel par défaut.
- N'ajoutez pas
ATTR_PERSISTENT. Les connexions persistantes ne corrigent pas l'erreur 1615 et s'accumulent sur un serveur partagé.
Comment corriger l'erreur 1615 ?
- Ouvrez le fichier
config/database.php de votre application.
- Dans le bloc
'mysql' => [ ... ], repérez la clé 'options'.
- Ajoutez la ligne
PDO::ATTR_EMULATE_PREPARES => true, dans le tableau des options. Avec la configuration fournie par les versions récentes de Laravel, le résultat ressemble à ceci :
'options' => extension_loaded('pdo_mysql') ? array_filter([
(PHP_VERSION_ID >= 80500 ? Mysql::ATTR_SSL_CA : PDO::MYSQL_ATTR_SSL_CA) => env('MYSQL_ATTR_SSL_CA'),
PDO::ATTR_EMULATE_PREPARES => true,
]) : [],
Si votre fichier contient une autre forme de 'options', ajoutez la même ligne dans son tableau, sans toucher au reste.
- Enregistrez le fichier et envoyez-le sur le serveur.
- Si vous avez mis la configuration en cache, reconstruisez-la en SSH, depuis le dossier de l'application :
php artisan config:cache
- Refaites l'opération qui provoquait l'erreur.
En cas de problème
| Ce que vous voyez |
Ce qu'il faut faire |
Class "Pdo\Mysql" not found |
La ligne utilise Pdo\Mysql:: alors que le site tourne sur PHP 8.3 ou antérieur. Remplacez Pdo\Mysql::ATTR_EMULATE_PREPARES par PDO::ATTR_EMULATE_PREPARES. |
| L'erreur 1615 continue après la modification |
La configuration est encore en cache : lancez php artisan config:cache (ou php artisan config:clear) dans le dossier de l'application. Vérifiez aussi que la ligne a été ajoutée dans le bloc mysql et non dans un autre pilote. |
| L'erreur apparaît hors de Laravel, dans un autre script PHP |
Le même réglage existe pour tout code qui utilise PDO : $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true); après la connexion. |
Pour aller plus loin