Bonjour à tous,
Je viens de commencer en local une petite webapplication de gestion.
j'utilise PDO et j'aimerai informer proprement et clairement l'utilisateur
(c'est à dire moi ou mon collègue) du pourquoi du non fonctionnement
de telle ou telle action.
En clair, comment récupérer l'erreur et afficher un message dans les
cas suivants :
try {
// Préparation de la requete :
$requete = $bdd->prepare('INSERT INTO fournisseurs(nom_fournisseur, rue_fournisseur, cp_fournisseur, ville_fournisseur) VALUES(:nom_fournisseur, :rue_fournisseur, :cp_fournisseur,:ville_fournisseur)');
$requete->execute(array(
'nom_fournisseur' => $nom_fournisseur,
'rue_fournisseur' => $rue_fournisseur,
'cp_fournisseur' => $cp_fournisseur,
'ville_fournisseur' => $ville_fournisseur
));
}
catch (PDOException $e){
echo 'L\'ajout du fournisseur a échoué !' . '<br />';
echo 'Erreur : '.$e->getMessage();
}
Et éviter ce genre de message :
L'ajout du fournisseur a échoué !
Erreur : SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'SARL MACHIN TRUC' for key 'nom_fournisseur'
Merci d'avance pour votre aide...
Salut,
La solution est assez simple, il te suffit de filtrer les messages d'erreur venant de MySQL et d'afficher ton propre message dans les cas qui t'interesse.
Regarde du coté des codes d'erreur de MySQL, ce sera plus simple pour trouver les erreurs via un regexp qui checkera $e->getMessage()
ou simplement récupérer le code via $e->getCode()
.
Un exemple ici: http://stackoverflow.com/a/5441494
Je dit pas que c'est la meilleur méthode, mais s'en est une, à toi de voir et de réfléchir à comment tu veux implementer ça.
Merci pour ton tuyau elhebert...
J'ai placé une contrainte de clé étrangère sur mon champ id_fournisseur dans ma table factures.
J'empèche la suppression du fournisseur (dans la table fournisseurs) qui possède encore des factures de cette manière :
if (isset($_GET['id'])) {
$id = $_GET['id'];
try {
// Préparation de la requète :
$req = "DELETE FROM fournisseurs WHERE id_fournisseur='$id'";
$req = $bdd->query($req);
$message='Le fournisseur a bien été supprimé...';
}
catch (PDOException $e){
$erreur = explode(':', $e->getMessage());
if($erreur[2]==1451){
echo 'Ce fournisseur possède encore des factures dans la base de données, il ne peut etre supprimé !';
}
else {
echo $e -> getMessage();
}
}
}
Est-ce propre ?
Sachant que l'erreur retournée est :
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (gescom
.factures
, CONSTRAINT factures_ibfk_1
FOREIGN KEY (id_fournisseur
) REFERENCES fournisseurs
(id_fournisseur
))
est-ce juste d'écrire cela : if($erreur[2]==1451)
Je veux dire ma commande récupère t-elle uniquement 1451 dans le message complet d'erreur ?
Tu devrais essayer avec le $e->getCode()
ce sera plus propre et demandera moins de ressource qu'un explode ;)
je te suggère de regarder ici pour plus d'infos: http://php.net/manual/fr/class.pdoexception.php
catch(Exception $e) {
echo "Le code de l'exception est : " . $e->getMessage();
}
Le problème c'est que je n'ai aucune idée du code php à créer pour récupérer le code exact de l'erreur.
Je récupère bien un 23000 pour une impossibilité à supprimer des données pour cause de contrainte
d'une clé étrangère mais également un 23000 pour une violation de clé unique ! J'ai l'impression que
quelque soit l'erreur , je tombe sur un 23000 ! Je ne peux donc pas personnaliser mon message
d'erreur !
Je pense qu'il faudrait plutôt utiliser un regexp (que je ne connais que de nom) comme tu le conseillais
pour récupérer un 1062 en cas de doublon ou un 1451 en cas de liaison avec une clé étrangère !
Ces codes ne sont ils pas stockés quelque part directement ailleurs que dans $e->getMessage() et donc
directement récupérables ?
Merci d'avance !
Bonsoir,
Je sais que je déterre un vieux topic, mais votre échange m'a aidé et voici moi ce que j'ai fait :
catch (PDOException $e)
{
$ErrorExplode = explode(': ', $e->getMessage());
//$Error = $ErrorExplode[0]; //inutile correspond à getCode();
$ErrorCode = $e -> getCode();
$Error = $ErrorExplode[1];
unset($ErrorExplode[0]);
unset($ErrorExplode[1]);
$ErrorEnd = implode(" : ",$ErrorExplode);
$ErrorExplode = explode(' ',$ErrorEnd);
$ErrorSQLCode = $ErrorExplode[0];
unset($ErrorExplode[0]);
$ErrorDescription = implode(" ",$ErrorExplode);
}
J'obtiens donc 4 variables :
$ErrorCode // contient le code erreur SQLState
$Error // contient la description de l'erreur SQLState
$ErrorSQLCode // contient le code erreur SQL
$ErrorDescription // contient la description de l'erreur SQL
!! Attention pour que le catch fonctionne, il faut ajouter une information sur la connexion PDO :
try
{
$DSN = 'mysql:host='.$dbserver.';port=3306;dbname='.$dbname.'';
$Connection = new PDO($DSN, $dbuser, $dbpass, array (PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''));
$Connection->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
$Connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
# print "Connection it's ok !";
}
catch ( PDOException $e )
{
print "Erreur !: " . $e->getMessage() . "<br/>";
die();
}
J'ai ajouté :
$Connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Bye
Pour info, on peut maintenant se passer du SET NAME 'UTF8' en rajoutant ;charset=utf8 dans la chaine de connexion