Problème INSERTION PDO : Fatal error: PDOException:

Default
,

Bonjour,

Voila je rencontre un petit problème avec mon code.

J'ai un code qui prépare et execute une requête.
Il y'a 13 champs dans la première partie de la requête prepare et 13 dans les values

A l'étape de l'execute, je n'en mets que 12 car un des champs va venir récupérer la date du jour.


if(!empty($_SESSION['login'])) {
    $membreID = $_SESSION['idMembre'];
    $membrelogin = $_SESSION['login'];

        if (!empty($_POST['titre']) AND !empty($_POST['chapo']) AND !empty($_POST['preparation']) AND !empty($_POST['ingredient']) AND !empty($_POST['tempsCuisson']) AND !empty($_POST['tempsPreparation']) AND !empty($_POST['difficulte']) AND !empty($_POST['prix'])) {
        $reqajout = $cooking->prepare("SELECT * FROM recettes WHERE titre = ?");
        $reqajout->execute(array($titre));
        $recetteexists = $reqajout->rowcount();
            if ($recetteexists === 0) {
            $ajoutrecette = $cooking->prepare("INSERT INTO recettes (titre, chapo, img, preparation, ingredient, membre, couleur, dateCrea, categorie, tempsCuisson, tempsPreparation, difficulte,prix) VALUES (:titre, :chapo, :img, :preparation, :ingredient, :membre, :couleur, NOW(), :categorie, :tempsCuisson, :tempsPreparation, :difficulte, :prix)");

            $ajoutrecette->execute(array(":titre"=> $titre, ":chapo"=> $chapo, ":img"=> $img, ":preparation"=> $preparation, ":ingredient"=> $ingredient, ":membre"=> $membreID, ":couleur"=> $couleur, ":categorie"=> $categorie, ":tempsCuisson"=> $tempsCuisson, ":tempsPreparation"=> $tempsPreparation, ":difficulte"=> $difficulte, ":prix"=> $prix));
            }
       }
}

Je voudrais que cette page permette à l'utilisateur d'uploader ses recettes et la photo du plat qu'il veut présenter.
J'ai réservé cette page aux membres inscrits et connectés d'où la déclaration au début.

A l'envoi du formulaire via mon bouton submit, j'ai un message d'erreur indiquant la ligne "$ajoutrecette->execute..."

( ! ) Fatal error: in C:\wamp64\www\cooking\ajoutrecette.php on line 51
( ! ) PDOException: in C:\wamp64\www\cooking\ajoutrecette.php on line 51
Call Stack

Time Memory Function Location

1 0.0004 407936 {main}( ) ...\ajoutrecette.php:0
2 0.0056 453496 execute ( ) ...\ajoutrecette.php:51

J'avais ma page d'inscription qui reposait sur le même principe: un nombre de champs inférieur dans la partie execute que dans la partie prepare car le champ de Date prenait aussi la valeur de la date actuelle.

Est ce que vous avez une piste?
Je ne vois pas pourquoi ce code me retourne une erreur alors que l'autre avait fonctionné (grâce à Carouge10 et Lartak) :)
Merci

15 Réponse

40917
,

Bonjour,
Les erreurs PDO sont-elles activés ?
Car là, la requête à l'air correcte

Default
,

Hello. Merci Carouge.
Oui, dans mon fichier database.inc.php que j'appelle au début, j'ai mis ce code:

<?php
$host= 'localhost';
$username= 'root';
$password= '';
$database= 'cooking';

try {
$cooking = new PDO("mysql:host=$host; dbname=$database", $username, $password);
$cooking->exec('SET CHARACTER SET UTF-8');
$cooking->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//$cooking->setAttribute(PDO::ATTR_EMULATE_PREPARES);
}
catch (PDOException $e) {
print "Erreur !: " . $e->getMessage() . "
";
die();
}
?>

J'ai mis en commentaire le 2nd SetAttributes qui me provoquait des erreurs car il fallait 2 arguments et je ne voyais pas quel autre argument placer.

40917
,

A quel moment tu fais $membre = $_POST['membre'] ? et de même pour les autres paramètres de la requêtes ?

Default
,

Carouge10,
au début, juste après leif(!empty($_SESSION['login'])) => je les avais supprimé pour une meilleure lecture:
if(!empty($_SESSION['login'])) {
$titre = filter_input(INPUT_POST,'titre');
$chapo = filter_input(INPUT_POST,'chapo');
$preparation = filter_input(INPUT_POST,'preparation');
$categorie = filter_input(INPUT_POST,'categorie');
$ingredient = filter_input(INPUT_POST,'ingredient');
$tempsCuisson = filter_input(INPUT_POST,'tempsCuisson');
$tempsPreparation = filter_input(INPUT_POST,'tempsPreparation');
$difficulte = filter_input(INPUT_POST,'difficulte');
$prix = filter_input(INPUT_POST,'prix');
$img = filter_input(INPUT_POST,'myfile');
$couleur = filter_input(INPUT_POST,'couleur');
$membreID = $_SESSION['idMembre'];
$membrelogin = $_SESSION['login'];

Pour un test, je viens de mettre en commentaire dans le fichier de connexion, la ligne de gestion des erreurs
$cooking->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Et ensuite repassé en actif, j'ai parfois eu l'erreur, parfois non.

Mais l'insertion dans ma BDD ne se fait pas. Je vais commencer à devenir fou avec ce code :)
Merci de ton aide

40917
,

as-tu testé le retour de la méthode execute de l'insert ?
Passes-tu au moins dans ce if ?
Quand tu mets du code ici, utilise le bouton </> comme tu l'as fais au début pour rendre ce code plus lisible.

Default
,

Qu'entends tu par retour?
Je ne passais plus dans la boucle avec le code que je t'ai donné, je viens de relancer.
Désolé, je n'avais plus mis dans le </> car ca avait déformé le texte.
Je retente:

<?php
//les 3 inc
include_once("inc/timer.inc.php");//session
include("inc/database.inc.php");//connexion cooking
include("inc/header.inc.php");

// test si remplissage et sécurité filter_input
if(isset($_SESSION['login'])) {
$titre = filter_input(INPUT_POST,'titre');
$chapo = filter_input(INPUT_POST,'chapo');
$preparation = filter_input(INPUT_POST,'preparation');
$categorie = filter_input(INPUT_POST,'categorie');
$ingredient = filter_input(INPUT_POST,'ingredient');
$tempsCuisson = filter_input(INPUT_POST,'tempsCuisson');
$tempsPreparation = filter_input(INPUT_POST,'tempsPreparation');
$difficulte = filter_input(INPUT_POST,'difficulte');
$prix = filter_input(INPUT_POST,'prix');
$img = filter_input(INPUT_POST,'myfile');
$couleur = filter_input(INPUT_POST,'couleur');
$membreID = $_SESSION['idMembre'];
$membrelogin = $_SESSION['login'];
var_dump("test 1");
if (isset($_POST['titre']) AND isset($_POST['chapo']) AND isset($_POST['preparation']) AND isset($_POST['ingredient']) AND isset($_POST['tempsCuisson']) AND isset($_POST['tempsPreparation']) AND isset($_POST['difficulte']) AND isset($_POST['prix'])) {

    var_dump("test 2");
    $reqajout = $cooking->prepare("SELECT * FROM recettes WHERE titre = ?");
    $reqajout->execute(array($titre));
    $recetteexists = $reqajout->rowcount();
        if ($recetteexists === 0) {
        var_dump("test 3");
        // préparation et execution
        $ajoutrecette = $cooking->prepare("INSERT INTO recettes (titre, chapo, img, preparation, ingredient, membre, couleur, dateCrea, categorie, tempsCuisson, tempsPreparation, difficulte,prix) VALUES (:titre, :chapo, :img, :preparation, :ingredient, :membre, :couleur, NOW(), :categorie, :tempsCuisson, :tempsPreparation, :difficulte, :prix)");

        $ajoutrecette->execute(array(":titre"=> $titre, ":chapo"=> $chapo, ":img"=> $img, ":preparation"=> $preparation, ":ingredient"=> $ingredient, ":membre"=> $membreID, ":couleur"=> $couleur, ":categorie"=> $categorie, ":tempsCuisson"=> $tempsCuisson, ":tempsPreparation"=> $tempsPreparation, ":difficulte"=> $difficulte, ":prix"=> $prix));
        echo("Recette envoyée");
        //header('location: index.php');
        } else {
        $erreur = "la recette existe";
        }
    } else {
    $erreur = "tous les champs doivent être remplis";
    }
} else {
echo("vous devez être inscrit et connecté pour contribuer");
sleep(2);
header('location:index.php');
}
?>

J'ai mis en commentaire la ligne des erreurs dans mon fichier de connexion et passe mes différents tests de var_dump me montrent que j'arrive au test3 (après le 'if ($recetteexists === 0)'.
Mais l'insertion ne se fait toujours pas

EDIT: OK, je viens de comprendre pour le code, je l'utilisais mal. Désolé

40917
,

De souvenir, il vaut mieux éviter d'éditer ton code dans ton post.
La méthode execute te renvoie true ou false, ce qui te permet de savoir si elle c'est bien exécuter.
Compte le nombre de ? dans le prepare et compte le nombre de paramètre dans l'execute....

Default
,

J'ai 13 paramètres dans le prepare et 12 dans l'execute mais sur mon autre page d'inscription.

<?php
//Les 3 inc
include_once("inc/timer.inc.php");//session
include("inc/database.inc.php");//connexion cooking
include("inc/header.inc.php");

// Test si remplissage et sécurité filter_input

if (isset($_POST['formSubcription'])) {
    if (!empty($_POST['loginSub']) and !empty($_POST['prenom']) and !empty($_POST['nom']) and !empty($_POST['passwordSub'])) {
        $loginSub = filter_input(INPUT_POST, 'loginSub');
        $prenom = filter_input(INPUT_POST, 'prenom');
        $nom = filter_input(INPUT_POST, 'nom');

        //Essai avec sha1
        $passwordSub = sha1($_POST['passwordSub']);
        $passwordSub2 = sha1($_POST['passwordSub2']);

        //Test longueur login
        $loginSublength = strlen($loginSub);
        if ($loginSublength >= 4 and $loginSublength <= 10) {
        //requête pour voir si login déjà utilisé
        $reqloginSub = $cooking->prepare("SELECT * FROM membres WHERE login = ?");
        $reqloginSub->execute(array($loginSub));
        $loginSubexists = $reqloginSub->rowCount();
            if ($loginSubexists === 0) {
               if ($passwordSub2 === $passwordSub) {
                echo "Votre compte a bien été créé";
                //sleep (1);
                // Préparation et Execution
                $subcription = $cooking->prepare("INSERT INTO membres (gravatar,login,password,statut,prenom,nom,dateCrea) VALUES ('default.png',:login,:password,'membre',:prenom,:nom,NOW())");
                $subcription->execute(array(":login"=> $loginSub, ":password"=> $passwordSub, ":prenom"=> $prenom, ":nom"=> $nom)); 
                $connexion = $cooking->prepare("SELECT * FROM membres WHERE login = ? AND password= ?");
                $connexion->execute(array($loginSub, $passwordSub));
                $profil = $connexion->fetch();
                $_SESSION['idMembre'] = $profil['idMembre'];
                $_SESSION['login'] = $profil['login'];
                $_SESSION['password'] = $profil['password'];

                //Redirection
                header("Location: index.php");
                } else {
                $erreur = "Les mots de passe ne correspondent pas";
                }
            } else {
            $erreur = "Le login est déjà utilisé";
            }
        } else {
        $erreur = "Votre login doit être compris entre 4 et 10 caractères";
        }
    } else {
    $erreur = "Tous les champs doivent être remplis";
    }
}
?>

J'avais 7 paramètres dans le prepare et 5 dans l'execute et cela fonctionnait.
Du coup, je comprends pas ce qui bloque

40917
,

Oups, j'ai rien dis pour le faite de compter, ceci était pour une autre personne. J'ai mélanger les sujets.
Donc la tu arrives bien à avoir tes test X affichées ?
Que te renvoie la méthode execute ? true ou false ?

Default
,

Cela me retourne false:

<?php
include_once("inc/timer.inc.php");//session
include("inc/database.inc.php");//connexion cooking
include("inc/header.inc.php");

// test si remplissage et sécurité filter_input
if(isset($_SESSION['login'])) {
$titre = filter_input(INPUT_POST,'titre');
$chapo = filter_input(INPUT_POST,'chapo');
$preparation = filter_input(INPUT_POST,'preparation');
$categorie = filter_input(INPUT_POST,'categorie');
$ingredient = filter_input(INPUT_POST,'ingredient');
$tempsCuisson = filter_input(INPUT_POST,'tempsCuisson');
$tempsPreparation = filter_input(INPUT_POST,'tempsPreparation');
$difficulte = filter_input(INPUT_POST,'difficulte');
$prix = filter_input(INPUT_POST,'prix');
$img = filter_input(INPUT_POST,'myfile');
$couleur = filter_input(INPUT_POST,'couleur');
$membreID = $_SESSION['idMembre'];
$membrelogin = $_SESSION['login'];
var_dump("test 1");
    //if (!empty($_POST['titre']) AND !empty($_POST['chapo']) AND !empty($_POST['preparation']) AND !empty($_POST['ingredient']) AND !empty($_POST['tempsCuisson']) AND !empty($_POST['tempsPreparation']) AND !empty($_POST['difficulte']) AND !empty($_POST['prix'])) {
    if (isset($_POST['titre']) AND isset($_POST['chapo']) AND isset($_POST['preparation']) AND isset($_POST['ingredient']) AND isset($_POST['tempsCuisson']) AND isset($_POST['tempsPreparation']) AND isset($_POST['difficulte']) AND isset($_POST['prix'])) {

    var_dump("test 2");
    $reqajout = $cooking->prepare("SELECT * FROM recettes WHERE titre = ?");
    $reqajout->execute(array($titre));
    $recetteexists = $reqajout->rowcount();
        if ($recetteexists === 0) {
        var_dump("test 3");
        // préparation et execution
        $ajoutrecette = $cooking->prepare("INSERT INTO recettes (titre, chapo, img, preparation, ingredient, membre, couleur, dateCrea, categorie, tempsCuisson, tempsPreparation, difficulte,prix) VALUES (:titre, :chapo, :img, :preparation, :ingredient, :membre, :couleur, NOW(), :categorie, :tempsCuisson, :tempsPreparation, :difficulte, :prix)");

            if ($ajoutrecette->execute(array(":titre"=> $titre, ":chapo"=> $chapo, ":img"=> $img, ":preparation"=> $preparation, ":ingredient"=> $ingredient, ":membre"=> $membreID, ":couleur"=> $couleur, ":categorie"=> $categorie, ":tempsCuisson"=> $tempsCuisson, ":tempsPreparation"=> $tempsPreparation, ":difficulte"=> $difficulte, ":prix"=> $prix))) {
            echo 'true';
            } else {
            echo 'false';
            }
        }
    }   
}
?>
40917
,

le champs myfile est de type $_FILES ?

Default
,

Je suis pas sûr de voir comment le déclarer:

j'ai laissé que les éléments importants.
Est-ce que je mets sous cette forme-là:
$img = $_FILES['myfile'];

Et pour la déclaration du formulaire:
J'hésitais entre:

(mon premier choix car le fichier fileupload.inc.php ne devrait servir que pour l'upload de l'image (tout à la fin)
OU
<?php
//les 3 inc
include_once("inc/timer.inc.php");//session
include("inc/database.inc.php");//connexion cooking
include("inc/header.inc.php");

(...)

$img = $_FILES['myfile'];

    if (isset($_POST['titre']) AND isset($_POST['chapo']) AND isset($_POST['preparation']) AND isset($_POST['ingredient']) AND isset($_POST['tempsCuisson']) AND isset($_POST['tempsPreparation']) AND isset($_POST['difficulte']) AND isset($_POST['prix'])) {

    var_dump("test 2");
    $reqajout = $cooking->prepare("SELECT * FROM recettes WHERE titre = ?");
    $reqajout->execute(array($titre));
    $recetteexists = $reqajout->rowcount();
        if ($recetteexists === 0) {
        var_dump("test 3");
        // préparation et execution
        $ajoutrecette = $cooking->prepare("INSERT INTO recettes (titre, chapo, img, preparation, ingredient, membre, couleur, dateCrea, categorie, tempsCuisson, tempsPreparation, difficulte,prix) VALUES (:titre, :chapo, :img, :preparation, :ingredient, :membre, :couleur, NOW(), :categorie, :tempsCuisson, :tempsPreparation, :difficulte, :prix)");

            if ($ajoutrecette->execute(array(":titre"=> $titre, ":chapo"=> $chapo, ":img"=> $img, ":preparation"=> $preparation, ":ingredient"=> $ingredient, ":membre"=> $membreID, ":couleur"=> $couleur, ":categorie"=> $categorie, ":tempsCuisson"=> $tempsCuisson, ":tempsPreparation"=> $tempsPreparation, ":difficulte"=> $difficulte, ":prix"=> $prix))) {
            echo 'true';
            } else {
            echo 'false';
            }
        }
    }   
}
?>

<!doctype html>
<html>
<body>
    <div class="container-fluid">
        <div class="container">
            <div class="row">

                <form method="post" action="">
                OU
                <form method="post" action="fileupload.inc.php">

(...)

                    <div class="form-group">
                        <label for="photo">Photo du plat</label>
                        <form action="fileupload.inc.php" method="POST" enctype="multipart/form-data">
                        <input type="hidden" name="MAX_FILE_SIZE" value="2000000" />
                        <input type="file" name="myfile" id="filetoupload">
                        <input type="submit" name="submit" value="téléverser la photo du plat">
                    </div><br>

(...)

                    <input type="submit" name="formajout" value="Déposer la recette">
                </form>
            </div>
        </div>
    </div>
</body>
<?php
//footer
include("inc/footer.inc.php");
?>

</html>

Mon fichier 'fileupload.inc.php':

<?php
    $currentDir = getcwd();
    $uploadDirectory = "/uploads/";

    $erreurs = [];

    $fileExtensions = ['jpeg','jpg','png','gif'];

    $fileName = $_FILES['myfile']['name'];
    $fileSize = $_FILES['myfile']['size'];
    $fileTmpName  = $_FILES['myfile']['tmp_name'];
    $fileType = $_FILES['myfile']['type'];
    $fileExtension = strtolower(end(explode('.',$fileName)));

    $uploadPath = $currentDir . $uploadDirectory . basename($fileName); 

    if (isset($_POST['submit'])) {

        if (! in_array($fileExtension,$fileExtensions)) {
        $erreurs[] = "Extension non supportée. Veuillez uploader un png, jpeg, jpg ou gif";
        }
        if ($fileSize > 2000000) {
        $erreurs[] = "Veuillez envoyer un fichier de moins de 2mo";
        }
        if (empty($erreurs)) {
            $didUpload = move_uploaded_file($fileTmpName, $uploadPath);
            if ($didUpload) {
            echo "Le fichier " . basename($fileName) . " a été uploadé";
            } else {
            echo "Erreur. Veuillez réessayer";
            }
        } else {
            foreach ($erreurs as $erreur) {
            echo $erreur . "Voici les erreurs" . "\n";
            }
        }
    }

?>
40917
,

$img est un array donc tu ne peux mettre ton array en tant paramètre
puisque que tu connais le chemin vers ton image, il te faut stocker seulement le nom de cette dernière.

Default
,

Je ne suis pas sûr de comprendre.
Tu veux dire sous cette forme?

là-haut, je garde:

$img = $_FILES['myfile'];

et dans la requête:

":img"=> $img['fileName'],

ce qui donne

      if ($ajoutrecette->execute(array(":titre"=> $titre, ":chapo"=> $chapo, ":img"=> $img['fileName'], ":preparation"=> $preparation, ":ingredient"=> $ingredient, ":membre"=> $membreID, ":couleur"=> $couleur, ":categorie"=> $categorie, ":tempsCuisson"=> $tempsCuisson, ":tempsPreparation"=> $tempsPreparation, ":difficulte"=> $difficulte, ":prix"=> $prix))) {
            echo 'true';
            } else {
            echo 'false';
            }

Je n'avais pas créé ce fichier d'upload pour être honnête, je l'avais trouvé sur internet pour l'étudier

Default
,

When you put code here, use the </> button as you did at the beginning to make this code more readable. Redtube Beeg Spankbang