Je suis bloqué dans la création de mon backend, svp besoin d'aide d'un génie du PHP !!

Petit nouveau ! | 5 Messages

17 nov. 2023, 16:06

Bonjour la commu, j'ai créé un petit site de vente, et je créé maintenant le backend, donc j'ai créé une page pour afficher mes produits, depuis laquelle on peut editer chacun de ces produits. Mais quand je clique sur le bouton "submit", la page suis le header, mais les changements ne sont pas effectués.
J'ai beaucoup cherché, mais je séche là.

Voici mon code :

la page principale (afficher.php):
<?php

require("commandes.php");

$produits=afficher();
$nom="PokeCards";
?>

<!DOCTYPE html>

<html lang="fr">

  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="shortcut icon" href="../images/navbar/logo.png" type="image/png">    
    <title>Admin - Tous les produits</title>
    <!--Google Fonts-->
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;300;400;500;600;700;800;900&family=Roboto+Flex:opsz,[email protected],100;8..144,300;8..144,500;8..144,700;8..144,900&display=swap" rel="stylesheet" />
    <link href="bootstrap.min.css" rel="stylesheet" />
    <link href="fontawesome-free-6.4.2-web/css/all.min.css" rel="stylesheet" />
    <!--CSS Style-->
    <style type="text/css">
    	.containeur-fluid{
    		position: absolute;
    		top: 10px;
    		left: 0px;
    		display: inherit;
    		margin-bottom: 10px;
    	}

    	.container{
    		position: absolute;
    		top: 70px;
    		left: 100px;
    	}
    </style>
  </head>

  <body>

  <nav class="navbar navbar-expand-lg navbar_light bg-light">
  	<div class="containeur-fluid">
  		<a class="navbar-brand" href="../" style="color: cadetblue; font-weight: 400;">// PokeCards Boutique //</a>
  		<button class="navbar-toggler"
  				type="button"
		  		data-bs-toggle="collapse"
		  		data-bs-target="#navbarSupportedContent"
		  		aria-controls="navbarSupportedContent"
		  		aria-expanded="false"
		  		aria-label="Toggle navigation">
  				<span class="navbar-toggler-icon"></span>
  		</button>
  		<div class="collapse navbar-collapse" id="navbarSupportedContent">
  			<ul class="navbar-nav me-auto mb-lg-0">
  				<li class="nav-item">
  					<a class="nav-link active"
  					   style="font-weight: bold;"
  					   aria-current="page" 
  					   href="afficher.php">Produits</a>
  				</li>
  				<li class="nav-item">
  					<a class="nav-link"
  					   aria-current="page"
  					   href="nouveau.php"
  					   style="color: cadetblue; font-weight: 400;">Nouveau</a>
  				</li>
  				 <li class="nav-item">
  					<a class="nav-link"
  					   aria-current="page"
  					   href="supprimer.php"
  					   style="color: cadetblue; font-weight: 400;">Suppression</a>
  				</li>
  				 <li class="nav-item">
  					<a class="nav-link"
  					   aria-current="page"
  					   href="#"
  					   style="color: cadetblue; font-weight: 400;">Modification</a>
  				</li>
  			</ul>
  		</div>
  		<a class="btn btn-danger d-flex" style="display: flex; justify-content: flex-end;" href="../logout.php">Déconnexion</a>
  	</div>
  	<div style="position: absolute; top: 17px;left: 730px;" >
  		<h5 style="color: cadetblue;opacity: 1.0;"><?=$nom?></h5>
  	</div>
  </nav>
  	<div class="album py-5 bg-light">
  		<div class="container">
  			<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3">
  				<table class="table">
  					<thead>
  						<tr>
  							<th scope="col">#</th>
  							<th scope="col">image</th>
  							<th scope="col">nom</th>
  							<th scope="col">collection</th>
  							<th scope="col">infoscarte</th>
  							<th scope="col">etat</th>
  							<th scope="col">prix</th>
  							<th scope="col">disponibilite</th>
  							<th scope="col">stock</th>
  							<th scope="col">éditer</th>
  						</tr>
  					</thead>
						<?php foreach ($produits as $produit): ?>
						    <tr>
						        <th scope="row"><?= $produit->id ?></th>
						        <td><img src="../images/cartes/<?= $produit->image_produit ?>" style="width:69%"></td>
						        <td><?= $produit->nom_produit ?></td>
						        <td><?= $produit->collection_produit ?></td>
						        <td><?= substr($produit->infoscarte_produit,0,100) ?>...</td>
						        <td><?= $produit->etat_produit ?></td>
						        <td style="font-weight:bold;color:green;"><?= $produit->prix_produit ?> Euros</td>
						        <td><?= $produit->disponibilite_produit ?></td>
						        <td><?= $produit->stock_produit ?></td>
						        <td><a href="editer.php?id=<?= $produit->id ?>"><i class="fa fa-pencil" style="font-size:30px;"></i></a></td>
						    </tr>
						<?php endforeach; ?>
  				</table>
  			</div>
  		</div>
  	</div>

  </body>
</html>

la page d'édition 'editer.php):
<?php

error_reporting(E_ALL);
ini_set('display_errors', 1);

require("commandes.php");
$id=$_GET['id'];
$leProduit=afficherUnproduit($id);
$nom="PokeCards";

?>

<!DOCTYPE html>

<html lang="fr">

  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="shortcut icon" href="../images/navbar/logo.png" type="image/png">    
    <title>Admin - Editer les Produits</title>
    <!--Google Fonts-->
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;300;400;500;600;700;800;900&family=Roboto+Flex:opsz,[email protected],100;8..144,300;8..144,500;8..144,700;8..144,900&display=swap" rel="stylesheet" />
    <link href="bootstrap.min.css" rel="stylesheet" />
    <link href="fontawesome-free-6.4.2-web/css/all.min.css" rel="stylesheet" />
    <!--CSS Style-->
    <style type="text/css">
      .containeur-fluid{
        position: absolute;
        top: 10px;
        left: 0px;
        display: inherit;
        margin-bottom: 10px;
      }

      .bg-light {
        --bs-bg-opacity: 0;
        background-color: rgba(var(--bs-light-rgb),var(--bs-bg-opacity)) !important;
      }

      .container{
        position: absolute;
        top: 70px;
        left: 100px;
      }

      h5{
        text-align: center;
      }

      .btn btn-success{
        display: block;
        width: 310px;
        padding-left: 8px;
        padding-right: 8px;
      }

      .retourproduitspanel{
        text-decoration: none;
        background-color: #198754;
        padding: 8px;
        border-radius: 5px;
        text-align: center;
        color: white;
        display: block;
        width: 310px;
        transition: color .15s ease-in-out,
                          background-color .15s ease-in-out,
                          border-color .15s ease-in-out,
                          box-shadow .15s ease-in-out;
        margin-bottom: 30px;
      }

      .retourproduitspanel:hover{
        background-color: #157347; 
        transition: color .15s ease-in-out,
                          background-color .15s ease-in-out,
                          border-color .15s ease-in-out,
                          box-shadow .15s ease-in-out;      
      }

    </style>
  </head>

  <body>

    <nav class="navbar navbar-expand-lg navbar_light bg-light">
      <div class="containeur-fluid">
        <a class="navbar-brand" href="../" style="color: cadetblue; font-weight: 400;">// PokeCards Boutique //</a>
        <button class="navbar-toggler" 
            type="button" 
            data-bs-toggle="collapse" 
            data-bs-target="#navbarSupportedContent" 
            aria-controls="navbarSupportedContent" 
            aria-expanded="false" 
            aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav me-auto mb-lg-0">
            <li class="nav-item">
              <a class="nav-link"
                 aria-current="page" 
                 href="afficher.php"
                 style="color: cadetblue; font-weight: 400;">Produits</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" 
                 aria-current="page" 
                 href="nouveau.php"
                 style="color: cadetblue; font-weight: 400;">Nouveau</a>
            </li>
             <li class="nav-item">
              <a class="nav-link" 
                 aria-current="page" 
                 href="supprimer.php"
                 style="color: cadetblue; font-weight: 400;">Suppression</a>
            </li>
             <li class="nav-item">
              <a class="nav-link active" 
                 style="font-weight: bold;
                 color: green"
                 aria-current="page" 
                 href="">Modification</a>
            </li>
          </ul>
        </div>
        <a class="btn btn-danger d-flex" style="display: flex; justify-content: flex-end;" href="../logout.php">Déconnexion</a>
      </div>
      <div style="position: absolute; top: 17px;left: 730px; font-weight: bold;" >
        <h5 style="color: cadetblue;opacity: 1.0;"><?=$nom?></h5>
      </div>
    </nav>

    <div class="album py-5 bg-light">
      <div class="container">
        <div class="row-cols-1 row-cols-sm-2 row-cols-md-3 g-3">
          <?php foreach($leProduit as $produit): ?>
            <form method="POST">
              <h5>Edition du produit sélectionné</h5>
              <div class="mb-3">
                <label for="input1" class="form-label">L'image d'illustration de ce produit</label>
                <input type="text" class="form-control" name="image_produit" value="<?=$produit->image_produit?>" required>
              </div>
              <div class="mb-3">
                <label for="input2" class="form-label">Le nom de ce produit</label>
                <input type="text" class="form-control" name="nom_produit" value="<?=$produit->nom_produit?>" required>
              </div>
              <div class="mb-3">
                <label for="input2" class="form-label">La collection/série de ce produit</label>
                <input type="text" class="form-control" name="collection_produit" value="<?=$produit->collection_produit?>" required>
              </div>
              <div class="mb-3">
                <label for="input2" class="form-label">L'état de qualité de ce produit</label>
                <input type="text" class="form-control" name="etat_produit" value="<?=$produit->etat_produit?>" required>
              </div>
              <div class="mb-3">
                <label for="input2" class="form-label">La description de ce produit</label>
                <textarea class="form-control" name="infoscarte_produit" required><?=$produit->infoscarte_produit?></textarea>
              </div>
              <div class="mb-3">
                <label for="input2" class="form-label">Le prix de ce produit</label>
                <input type="number" class="form-control" name="prix_produit" value="<?=$produit->prix_produit?>" required>
              </div>
              <div class="mb-3">
                <label for="input2" class="form-label">La disponibilité ou non de ce produit</label>
                <input type="text" class="form-control" name="disponibilité_produit" value="<?=$produit->disponibilite_produit?>" required>
              </div>
              <div class="mb-3">
                <label for="input2" class="form-label">L'état des stocks de ce produit</label>
                <input type="text" class="form-control" name="stock_produit" value="<?=$produit->stock_produit?>" required>
              </div>
              <button type="submit" name="valider" 
                      class="btn btn-success">Enregistrer les modifications</button>
            </form>
          <?php endforeach; ?>
          <br />
          <a href="afficher.php" class="retourproduitspanel">Retour aux produits sans rien modifier</a>
        </div>
      </div>
    </div>

  </body>
</html>

<?php
  if(isset($_POST['valider']))
  {
    if(isset($_POST['image_produit']) AND isset($_POST['nom_produit']) AND isset($_POST['collection_produit']) AND isset($_POST['etat_produit']) AND isset($_POST['infoscarte_produit']) AND isset($_POST['prix_produit']) AND isset($_POST['disponibilite_produit']) AND isset($_POST['stock_produit']))
    {
      if(!empty($_POST['image_produit']) AND !empty($_POST['nom_produit']) AND !empty($_POST['collection_produit']) AND !empty($_POST['etat_produit']) AND !empty($_POST['infoscarte_produit']) AND !empty($_POST['prix_produit']) AND !empty($_POST['disponibilite_produit']) AND !empty($_POST['stock_produit']))
      {
        $image=htmlspecialchars(strip_tags($_POST['image_produit']));
        $nome=htmlspecialchars(strip_tags($_POST['nom_produit']));
        $collection=htmlspecialchars(strip_tags($_POST['collection_produit']));
        $etat=htmlspecialchars(strip_tags($_POST['etat_produit']));
        $infoscarte=htmlspecialchars(strip_tags($_POST['infoscarte_produit']));
        $prix=htmlspecialchars(strip_tags($_POST['prix_produit']));
        $disponibilite=htmlspecialchars(strip_tags($_POST['disponibilite_produit']));
        $stock=htmlspecialchars(strip_tags($_POST['stock_produit']));
        if(isset($_GET['id']))
        {
          if(!empty($_GET['id']) OR is_numeric($_GET['id']))
          {
            $id=$_GET['id'];
          }
        }
        try
        {
          modifier($image,$nom,$collection,$etat,$infoscarte,$prix,$disponibilite,$stock,$id);
          header('Location: afficher.php');
        }
        catch (Exception $e)
        {
          $e->getMessage();
        }
      }
    }
  }
?>
la page qui fait le lien entre la page d'édition, et la bdd (commande.php):

<?php

error_reporting(E_ALL);
ini_set('display_errors', 1);

function ajouter($image, $nom, $collection, $etat, $infoscarte, $prix, $disponibilite, $stock, $id)
{
    if (require("connexion.php"))
    {
        $req=$access->prepare("INSERT INTO cartes (image_produit, nom_produit, collection_produit, etat_produit, infoscarte_produit, prix_produit, disponibilite_produit, stock_produit) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
        $req->execute(array($image, $nom, $collection, $etat, $infoscarte,  $prix, $disponibilite, $stock));
        $req->closeCursor();        
    }
}

function afficher()
{
    if (require("connexion.php"))
    {
        $req=$access->prepare("SELECT * FROM cartes ORDER BY id DESC");
        $req->execute();
        $data=$req->fetchAll(PDO::FETCH_OBJ);
        return $data;
        $req->closeCursor();        
    }
}

function afficherUnproduit($id)
{
    if (require("connexion.php"))
    {
        $req=$access->prepare("SELECT * FROM cartes WHERE id=?");
        $req->execute(array($id));
        $data=$req->fetchAll(PDO::FETCH_OBJ);
        return $data;
        $req->closeCursor();        
    }
}

function modifier($image, $nom, $collection, $etat, $infoscarte, $prix, $disponibilite, $stock, $id)
{
    if (require("connexion.php"))
    {
        $req=$access->prepare("UPDATE cartes SET image_produit=?,nom_produit=?,collection_produit=?,etat_produit=?,infoscarte_produit=?,prix_produit=?,disponibilite_produit=?,stock_produit=? WHERE id=?");
        $req->execute(array($image,$nom,$collection,$etat,$infoscarte,$prix,$disponibilite,$stock,$id));
        $req->closeCursor();        
    }
}

function supprimer($id)
{
    if(require("connexion.php"))
    {
        $req=$access->prepare("DELETE FROM cartes WHERE id=?");
        $req->execute(array($id));
        $req->closeCursor();
    }
}

?>


et la page de connexion (connexion.php):
<?php

error_reporting(E_ALL);
ini_set('display_errors', 1);

try
{
	$access=new pdo("mysql:host=localhost;dbname=***;charset=utf8", "***", "");
}
catch (Exception $e)
{
	$e->getMessage();
}
?>
J'espère trouver un peu d'aide, tchuss !
Modifié en dernier par spaghetification le 17 nov. 2023, 17:33, modifié 6 fois.

Avatar du membre
Mammouth du PHP | 1564 Messages

17 nov. 2023, 16:42

Salut, bienvenue sur le forum, met ton code dans les balises du forum pour le mettre en valeur.

Petit nouveau ! | 5 Messages

17 nov. 2023, 17:21

Salut, bienvenue sur le forum, met ton code dans les balises du forum pour le mettre en valeur.
c'est fait merci du conseil
Modifié en dernier par spaghetification le 17 nov. 2023, 18:47, modifié 1 fois.

Avatar du membre
Mammouth du PHP | 1564 Messages

17 nov. 2023, 18:37

Merci pour la colorisation syntaxique. ;)

As-tu ds erreurs dans le log local ? Tu travail en local ? Regarde dans le log d'erreurs PHP voir si ya des erreurs de requête SQL.

Sinon, gère les erreurs lors de tes requêtes, ne te contente pas de faire seulement modifier(...); mais if(!modifier(...)){afficher erreur ici}else{afficher un msg succès}

Mammouth du PHP | 2703 Messages

17 nov. 2023, 18:56

<form method="POST">


if(isset($_GET['id']))
{
if(!empty($_GET['id']) OR is_numeric($_GET['id']))
{
$id=$_GET['id'];
}
}
try
{
modifier($image,$nom,$collection,$etat,$infoscarte,$prix,$disponibilite,$stock,$id);

pour modifier un produit, il faut vraiment avoir son id, ce qui n'est pas le cas avec ce code.

ps : après vérification, ce que j'ai dit est faux, l'id est bien passé quand la page est appelée en méthode post.
Modifié en dernier par or 1 le 17 nov. 2023, 19:19, modifié 1 fois.

Petit nouveau ! | 5 Messages

17 nov. 2023, 18:59

J'ai regardé le fichier log de php à l'instant après avoir tenté une modification d'un produit du shop (qui n'a pas fonctionné), mais aucune ereure répertorié dans le fichier log.
Je vais regarder ton autre conseil.

Avatar du membre
Mammouth du PHP | 1564 Messages

17 nov. 2023, 19:25

Je vois que tu as mis un try/catch, pour arrêter le script, c'est bien mais il te faut lancer une erreur via
throw new Exception(message d'erreur ici);
ou au moins :
throw new Exception;

Ce que j'ai coloré en rouge sera contenu dans "$e->getMessage()".

Lors de ta requête PDO, vérifie si elle a bien été exécutée, sinon lance une exception. ;)

Mammouth du PHP | 2703 Messages

17 nov. 2023, 19:44

modifier($image,$nom,$collection,$etat,$infoscarte,$prix,$disponibilite,$stock,$id);
header('Location: afficher.php');
elle se fait cette redirection vers afficher.php ? ou cela reste sur la page d'édition d'un produit ?

Petit nouveau ! | 5 Messages

17 nov. 2023, 22:46

modifier($image,$nom,$collection,$etat,$infoscarte,$prix,$disponibilite,$stock,$id);
header('Location: afficher.php');
elle se fait cette redirection vers afficher.php ? ou cela reste sur la page d'édition d'un produit ?
justement, on reste sur la même page . la modification ne se fait pas et on reste sur la page editer.php

Mammouth du PHP | 2703 Messages

17 nov. 2023, 23:27

le select est fait avant l'update. donc quand vous validez le formulaire, la page se réaffiche avec les données en base de données, et ensuite, la mise à jour de la base de données se fait. il faut donc vérifier, par exemple, en retournant sur la liste des produits si la mise à jour s'est bien faite.
et faire l'update en début de script, ce qui permettra à la redirection de fonctionner.

Petit nouveau ! | 5 Messages

18 nov. 2023, 00:18

le select est fait avant l'update. donc quand vous validez le formulaire, la page se réaffiche avec les données en base de données, et ensuite, la mise à jour de la base de données se fait. il faut donc vérifier, par exemple, en retournant sur la liste des produits si la mise à jour s'est bien faite.
et faire l'update en début de script, ce qui permettra à la redirection de fonctionner.
ok excellent est-ce possible de me montrer le bout de code modifié sans vouloir abuser ?

Avatar du membre
Mammouth du PHP | 1609 Messages

21 nov. 2023, 16:13

Salut, 3 if sans aucun else, ce genre de codes est vraiment pas terrible. C'est ennuyeux à écrire, à lire, à vérifier et à maintenir...

  if(isset($_POST['valider']))
  {
    if(isset($_POST['image_produit']) AND isset($_POST['nom_produit']) AND isset($_POST['collection_produit']) AND isset($_POST['etat_produit']) AND isset($_POST['infoscarte_produit']) AND isset($_POST['prix_produit']) AND isset($_POST['disponibilite_produit']) AND isset($_POST['stock_produit']))
    {
      if(!empty($_POST['image_produit']) AND !empty($_POST['nom_produit']) AND !empty($_POST['collection_produit']) AND !empty($_POST['etat_produit']) AND !empty($_POST['infoscarte_produit']) AND !empty($_POST['prix_produit']) AND !empty($_POST['disponibilite_produit']) AND !empty($_POST['stock_produit']))
      {

Alors pour le premier if ok, même si ça serait mieux de l'avoir tout en haut comme suggéré par or1, ça éviterait au moins que tout le reste au dessus s'exécute dans le cas d'une modification. Quel intérêt de construire l'affichage de la page pour finir avec une redirection ? le serveur bosse pour rien.

Pour les isset et les !empty, il n'y a pas de else, on pourrait donc parier que dans ton cas l'un ou l'autre des 2 if n'est pas vrai et la création/modification et la redirection ne sont donc pas faites.

Tu devrais plutôt lister les noms de tes champs dans un tableau et faire une ou deux boucles pour les contrôler.

<?php
if(isset($_POST['valider'])) {
    $inputs = ['image_produit', 'nom_produit'/*, etc */];
    $errors = [];

    foreach ($inputs as $input) {
        if (!isset($_POST[$input])) {
            /* ici on est surtout sur un contrôle du code car les inputs sont sensés être bien définis, 
            mais en admettant qu'un input soit mal nommé, ça passera ici ! */
            $errors[$input] = "$input is not defined.";
        } elseif (empty($_POST[$input])) {
            $errors[$input] = "$input is empty.";
        }
    }

    if (count($errors) === 0) {
        /* il n'y a pas d'erreurs, procéder aux traitements et rediriger */
        // traitements ...

        /* redirection */
        header('Location: /* ... */');
        /* ne pas oublier de sortir pour éviter que le serveur exécute les traitements en dessous */
        exit();
    }
}

/* quelque part dans la page plus bas, la où tu veux afficher les erreurs */
/* théoriquement le isset suffit étant donné que s'il n'y avait pas d'erreur on a été redirigé */
if (isset($errors) && count($errors) > 0) {
    /* boucler sur le tableau $errors pour afficher les erreurs */
}

/* dans l'idéal adapter le formulaire pour reprendre les valeurs des inputs dans POST quand elles 
sont définies */
?>
    <input type="text" class="form-control" name="nom_produit"
           value="<?php echo $_POST['nom_produit'] ?? $produit->nom_produit; ?>" required>

<?php
/* tu peux même adapter la class de l'input pour modifier son apparence, il faut bien sur déclarer la 
class dans la CSS, ici on dirait du bootstrap, il doit donc déjà y avoir ce qu'il faut, il faut juste 
trouver le bon nom de class */
?>
    <input type="text" class="form-control <?php echo isset($errors) && isset($errors['nom_produit']) ? 'form-control-error' : ''  ?>" name="nom_produit"
           value="<?php echo $_POST['nom_produit'] ?? $produit->nom_produit; ?>" required>

<?php
/* on peut également éviter tous les tests isset($errors) simplement en déclarant $errors avant le if 
isset POST valider */
?>

Ainsi même si c'est pas parfait, le code est déjà beaucoup plus lisible et bien plus facile à maintenir/déboguer et en cas d'erreur l'utilisateur n'a pas à reprendre toutes ses modifications.
Développeur web depuis + de 20 ans