[RESOLU] création objet

Eléphant du PHP | 66 Messages

05 nov. 2023, 17:33

bonjour

je veux générer aléatoirement :
un nombre d'élève,
chaque élève est affecté à une des 3 écoles
chaque élève pratique entre 0 et 3 sports parmi 5 sports

voici les table que j'ai créé
table école : ecole_id |ecole_nom
table sport : sport_id | sport_nom
table élevé : eleve_id | ecole_id | nbrSport
table sportEleve : sportEleve_id | eleve_id | sport_id

j'arrive à générer les datas pour la table élève.

1IERE problématique
là ou cela se gâte c'est pour la sélection des sports parmi les 5 : j'ai fait le choix d'utiliser un array_rand mais si le nombre de sport n'est pas de 3 j'ai un message d'erreur car il y a des valeurs NULL.

2ieme problématique
comment faire pour générer les datas pour la table sportEleve mon problème est pour eleve_id qui ne ne pas changer si l'élève pratique plusieurs sports.

dans mon code j'ai inclu le array_rand mais pas du tout fait de ligne de code car je ne vois pas comment m'y prendre.

il y a-t-il une bonne âme pour me guider. Merci d'avance pour votre aide

page -> index.php
<?php
require('objets.php');
//condition pour les stat aléatoirement
if (isset($_GET["lancer"])) {
    //nombre d'élève générer aléatoirement
    $nbrEleve = rand(10,30);
    //boucle création eleve (affectation ecole, nbr de sports, selection des sports)
    for ($i=0; $i < $nbrEleve; $i++) {
        //affectation de l'id de l'école
        $school_id = rand(1,3);
        //affectation du nombre de sport
        $nbrSports = rand(0,3);
        //tableau de selection aléatoire du nombre de sports
        $input = array(1, 2, 3, 4, 5);
        $rand_keys = array_rand($input, $nbrSports);
        $sport1 = $input[$rand_keys[0]];
        $sport2 = $input[$rand_keys[1]];
        $sport3 = $input[$rand_keys[2]];    
        //création de l'objet eleve
        $eleve_data = array(
            'ecole_id' => $school_id,
            'nbrSport' => $nbrSports,            
        );
        $eleve = new Eleve($eleve_data);  


        //affectation dans la variable $db de la connexion PDO
        $db = new PDO('mysql:host=localhost;dbname=statecole', 'root', '');

        //instanciation de la classe EleveManager, nous créons un objet breve en argument
        //la connexion PDO est passée en paramètre au constructeur.
        $manager = new EleveManager($db); 

        //appel de la méthode addPupil, nous passons un objet eleve en argument.
        $manager->addEleve($eleve);
    }
}

?>


<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="./styles.css" media="screen">   
    <title>php avancé 1</title>
</head>
<body>
    <!--header - titre de la page-->
    <header>
        <h1>php avancé 1</h1>
    </header>
    <!--main et div bouton d'action pour les stats aléatoirement-->
    <main>        
        <div class="stat">
            <h2>Lancement des stats aléatoires</h2>
            <form action="index.php" method="get">
                <input type="submit" name="lancer" value="générer les stats" >
            </form>
        </div>  
        <br><br>
    <!--pied de page-->
    <footer>
        <p>Les données sont générer aleatoirement</p>
    </footer>    
</body>
</html>
la page objets.php
<?php

// class eleve

class Eleve
{  
  private $_ecole_id;
  private $_nbrSports;
 

  public function __construct(array $eleveData)
  {    
    $this->setEcole_id($eleveData['ecole_id']);
    $this->setNbrSport($eleveData['nbrSport']);
    
  }

 // setters                                   
   
  public function setEcole_id($ecole_id)
  {
    if ((is_int($ecole_id)) AND ($ecole_id > 0) AND ($ecole_id < 4)) 
    {
      $this->_ecole_id = $ecole_id;
    }    
  }

 public function setNbrSport($nbrSports)
 {
   if ((is_int($nbrSports)) AND ($nbrSports >= 0) AND ($nbrSports <4)) 
    {
     $this->_nbrSports = $nbrSports;
    }
  }  

  
    
 // getters                                   

  public function getEcole_id()
  {
    return $this->_ecole_id;
  }

  public function getNbrSport()
  {
    return $this->_nbrSports;
  }

  
}

// class eleveManager

class EleveManager
{
  private $_db;

  public function __construct($db)
  {
    $this->setDb($db);
  }

  public function setDb(PDO $dbh)
  {
    $this->_db = $dbh;
  }

  //insertion des élèves dans la base de données
  public function addEleve(Eleve $eleve)
  {


    $sql = 'INSERT INTO eleve (ecole_id, nbrSport) VALUES (:ecole_id, :nbrSports)';
    $stmnt = $this->_db->prepare($sql);
    $ecole_id = $eleve->getEcole_id();
    $nbrSports = $eleve->getNbrSport();    
    $stmnt->bindParam(':ecole_id', $ecole_id);
    $stmnt->bindParam(':nbrSports', $nbrSports);    
    $stmnt->execute();

    //gestion des erreurs
    $errors = $stmnt->errorInfo();
    if ($errors[0] != '00000') 
    {
      echo 'Erreur SQL ' . $errors[2];
    }
    else
    {
       echo 'un élève a été ajouté';
    }

  }
}


Mammouth du PHP | 2703 Messages

05 nov. 2023, 18:05

1IERE problématique
comment avez-vous fait pour gérer le nombre d'élèves par classe qui est aussi aléatoire ?

2ieme problématique
https://www.php.net/manual/fr/pdo.lastinsertid.php

le champ nbrSport fait doublon avec le contenu de la table sportEleve
si vous supprimez un sport par la suite, il faut mettre à jour 2 tables. en virant ce champ de sportEleve, une seule, ce qui est mieux.

Eléphant du PHP | 66 Messages

05 nov. 2023, 18:38

merci pour le retour,

pour répondre à ta premier question

pour générer un nombre d'élevés j'ai fait : $nbrEleve = rand(10,30);
ensuite pour générer ecole_id et nbrSport, j'ai fait une boucle qui se répète $nbrEleve puis pour ecole_id : $school_id = rand(1,3); et pour nbrSport : $nbrSports = rand(0,3);

voici le code dessous.
<?php
require('objets.php');
//condition pour les stat aléatoirement
if (isset($_GET["lancer"])) {
    //nombre d'élève générer aléatoirement
    $nbrEleve = rand(10,30);
    //boucle création eleve (affectation ecole, nbr de sports, selection des sports)
    for ($i=0; $i < $nbrEleve; $i++) {
        //affectation de l'id de l'école
        $school_id = rand(1,3);
        //affectation du nombre de sport
        $nbrSports = rand(0,3);
pour la deuxième problématique, si je comprends bien je vire la table sportEleve et je transforma ma table élevé de la manière suivante ?
eleve_id | ecole_id | nbrSport | sport1_id | sport2_id | sport3_id

au départ j'avias fait comme cela mais après j'ai un problème lorsque je fais des requêtes SQL notamment pour faire la liste des sports pratiqués par école et le nombre d'élève qui pratique chaque sport. Comme je fais pour selectionner les 3 colonnes sport1_id, sport2_id et sport3_id

pour info je suis loin d'être un super pro de php

dans l'attente de ton retour et encore merci

Mammouth du PHP | 2703 Messages

05 nov. 2023, 19:52

pour la deuxième problématique, si je comprends bien je vire la table sportEleve et je transforma ma table élevé de la manière suivante ?
eleve_id | ecole_id | nbrSport | sport1_id | sport2_id | sport3_id
vous comprenez mal, relisez.

Eléphant du PHP | 66 Messages

05 nov. 2023, 20:16

bonjour je viens de relire :

voici les 4 table que j'ai crée :
voici les table que j'ai créé
table école : ecole_id |ecole_nom
table sport : sport_id | sport_nom
table élevé : eleve_id | ecole_id | nbrSport
table sportEleve : sportEleve_id | eleve_id | sport_id

vous avez écrire :
le champ nbrSport fait doublon avec le contenu de la table sportEleve
si vous supprimez un sport par la suite, il faut mettre à jour 2 tables. en virant ce champ de sportEleve, une seule, ce qui est mieux.

je suis désolé je ne comprends vraiment pas !!
sportElève est une table -> donc si je vire je supprime une table
vous dite une seule donc je comprends qu'il faille tout compiler dans une table

je suis complètement perdu .....

Mammouth du PHP | 2703 Messages

05 nov. 2023, 20:19

oups

en virant ce champ de eleve, une seule, ce qui est mieux.

Eléphant du PHP | 66 Messages

06 nov. 2023, 22:39

bon j'ai avancer sur ma problématique !! il me reste juste un dernier souci dans une partie de mon code.
dans mon foreach je récupère mes deux variables, jusque la pas de soucis, mon problème est dans la boucle for car eleve_id est null (info du message d'erreur).
donc j'en déduis que la valeur récupérer dans foreach n'est pas passer dans la boucle for.

je ne vois pas comme faire,??
il y a t-il une bonne âme pour me mettre sur la bonne piste
merci d'avance
 //récupération des résultats de la requête `SELECT`
        $stmt = $db->prepare('SELECT eleve_id, nbrSport FROM eleve');
        $stmt->execute();

        //variable pour stocker la valeur du paramètre `id_eleve`
        $eleve_id;

        //variable pour stocker la valeur du paramètre `prat_sports`
        $prat_sports;


        //boucle pour itérer sur les résultats
        foreach ($stmt->fetchAll() as $result) {
            //affectation des valeurs des résultats dans les variables
            $eleve_id = $result['eleve_id'];
            $prat_sports = $result['nbrSport'];

            //boucle pour générer les sports pratiqués
            for ($ii=0; $ii <= $prat_sports; $ii++) {
                //génération d'un nombre aléatoire compris entre 1 et 5
                $sportId = rand(1,5);               
                //création de l'objet sportEleve
                $sportEleve_data = array(
                    'eleve_id' => $eleve_id,
                    'sport_id' => $sportId,
                );
                $sportEleve = new SportEleve($sportEleve_data);
            }
        }

Eléphant du PHP | 66 Messages

06 nov. 2023, 23:03

j'ai passe la variable $eleve_id en variable global $eleve_id

mais toujours un problème eleve_id null !!

Fatal error: Uncaught PDOException: SQLSTATE[HY093]: Invalid parameter number: parameter was not defined in C:\code\phpAvance1\objets.php on line 173
( ! ) PDOException: SQLSTATE[HY093]: Invalid parameter number: parameter was not defined in C:\code\phpAvance1\objets.php on line 173
Call Stack
# Time Memory Function Location
1 0.0001 361592 {main}( ) ...\index.php:0
2 0.0421 476424 SportEleveManager->addSportEleve( $sportEleve = class SportEleve { private $_eleve_id = NULL; private $_sportId = 3 } ) ...\index.php:62

Mammouth du PHP | 2703 Messages

06 nov. 2023, 23:08

à quoi cela sert de faire un select sur les élèves quand on veut en rajouter un ?

Eléphant du PHP | 66 Messages

06 nov. 2023, 23:24

dans la table eleve je récupère eleve_id et nbrSport pour dans la table sporteleve pour chaque eleve_id génerer les sport_id. C'est un exercice que je dois faire

Eléphant du PHP | 66 Messages

06 nov. 2023, 23:24

dans la table eleve je récupère eleve_id et nbrSport pour insérer dans la table sporteleve pour chaque eleve_id génerer les sport_id. C'est un exercice que je dois faire

Mammouth du PHP | 2703 Messages

06 nov. 2023, 23:33

"je veux générer aléatoirement :
un nombre d'élève,
chaque élève est affecté à une des 3 écoles
chaque élève pratique entre 0 et 3 sports parmi 5 sports"

que se passe-t-il avec cette façon de faire si vous faites cette génération non pas une fois mais x fois ?

Eléphant du PHP | 66 Messages

06 nov. 2023, 23:46

dès le premier eleve j'ai le message d'erreur.

je pense avoir trouver mon problème qui semble venir des tables. j'explique :
dans la table eleve : eleve_id est int 5 et est la clé primaire de la table.

Maintenant lorsque je fait un var_dump sur eleve_id de ma boucle foreach voici le résultat : C:\code\phpAvance1\index.php:39:string '3032' (length=4)

Ce n'est pas normale que eleve_id soit un string alors que dans la table eleve eleve_id int 5?????
 //récupération des résultats de la requête `SELECT`
        $stmt = $db->prepare('SELECT eleve_id, nbrSport FROM eleve');
        $stmt->execute();

      
        //variable pour stocker la valeur du paramètre `id_eleve`
        global $eleve_id;

        //variable pour stocker la valeur du paramètre `prat_sports`
        global $prat_sports;


        //boucle pour itérer sur les résultats
        foreach ($stmt->fetchAll() as $result) {
            //affectation des valeurs des résultats dans les variables
            $eleve_id = $result['eleve_id'];
            $prat_sports = $result['nbrSport'];
            var_dump($eleve_id);
            //boucle pour générer les sports pratiqués
            for ($ii=0; $ii <= $prat_sports; $ii++){
                //génération d'un nombre aléatoire compris entre 1 et 5
                $sportId = rand(1,5);               
                //création de l'objet sportEleve
                $sportEleve_data = array(
                    'eleve_id' => $eleve_id,
                    'sport_id' => $sportId,
                );                
                $sportEleve = new SportEleve($sportEleve_data);
            }
        }
et voici les condition dans le setter
public function setEleve_id($eleve_id)
  {
    if ((is_int($eleve_id)) AND ($eleve_id > 0)) 
    {
      $this->_eleve_id = $eleve_id;
    }    
  

ynx
Mammouth du PHP | 586 Messages

07 nov. 2023, 12:04

PDO retourne les valeurs numériques avec un type string, tu peux utiliser le transtypage (type casting) pour convertir le type si tu veux mais ce n'est pas l'origine du problème.

Evite l'utilisation du mot-clé global, tu ne devrais pas en avoir besoin ici.

Il ne faut pas faire de requête SELECT pour récupérer l'identifiant de l'élève ajouté.
Pour compléter la réponse déjà donnée par or1, il faut utiliser la méthode lastInsertId pour récupérer l'identifiant :
1. On prépare une requête pour ajouter un éleve : $stmnt = $this->_db->prepare('INSERT INTO eleve...');
2. On bind les paramètres de la requête puis on exécute la requête : $stmnt->bindParam(':ecole_id', $ecole_id); $stmnt->execute();
3. Juste après l'exécution de la requête, on récupère l'identifiant de l'élève qui vient d'être ajouté : $id = $this->_db->lastInsertId();

Comme indiqué par or1, le champ nbrSport dans la table élevé est inutile et va te poser plus de problème que de solution.
Pour compter le nombre de sport d'un élève, il faut compter les lignes dans la table sportEleve pour un élève spécifié :
SELECT COUNT(*) AS nbrSport FROM sportEleve WHERE id_eleve = ?

Cette requête retourne déjà l'information nbrSport : le champ nbrSport dans la table eleve est redondant et donc inutile, à supprimer.

Eléphant du PHP | 66 Messages

07 nov. 2023, 23:20

merci pour ces informations précieuses !!
j'ai supprimé de la table eleve nbrSport.

la partie pour générer aléatoirement le nombre d'élève et les affecter à une ecole fonction bien.

c'est la deuxième partie du code qui merde et je tourne en rond #-o

ce que je veux faire :
récupérer les eleve_id
puis générer aléatoirement le nombre de sports pratiqués de 0 à 3 sports
puis générer aléatoire les sportId en fonction du nombre de sport pratiqué si 2 sports alors 2 sportId différents.

je ne sais pas si mon code fonction car j'ai une erreur au niveau du return $nombres -> Undefined variable $nombres in C:\code\phpAvance1\index.php on line 59
je ne comprends pas pourquoi la variable nombres n'est pas définie

hormis la variable undefined, le code est-il logique?
 //récupération des eleve_id
    $stmt = $db->prepare('SELECT eleve_id FROM eleve');
    $stmt->execute();
   

    //variable pour stocker la valeur du paramètre eleve_id
    $eleve_id;

    //boucle pour itérer sur les résultats
    foreach ($stmt->fetchAll() as $result) {
        //affectation des valeurs des résultats dans la variable
        $eleve_id = $result['eleve_id'];    
        //génération aléatoire du nombre de sport        
        $prat_sport = rand(0,3);
        function selectionnerNombresSansDoublons($prat_sport) {
            // Initialisation d'un tableau vide
            $nombres = [];
            // Boucle pour générer jusqu'a 3 nombres aléatoires
            for ($ii = 0; $ii < $prat_sport; $ii++) {
              // Génération des sportId aléatoire entre 1 et 5
              $nombre = rand(1, 5);
          
              // Vérification que le nombre n'est pas déjà dans le tableau
              if (!in_array($nombre, $nombres)) {
                // Ajout du nombre au tableau
                $nombres[] = $nombre;
              }
            }
        }      
            // Retour du tableau de nombres
            return $nombres;
            foreach ($nombres as $nombre){
                $sportId = $nombre;
                //création de l'objet sportEleve
                $sportEleve_data = array(
                    'eleve_id' => $eleve_id,
                    'sport_id' => $sportId,
                ); 
                //affectation dans la variable $db de la connexion PDO
                $db = new PDO('mysql:host=localhost;dbname=statecol', 'root', '');

                //instanciation de la classe EleveManager, nous créons un objet breve en argument
                //la connexion PDO est passée en paramètre au constructeur.
               
                $manager1 = new SportEleveManager($db);

                //appel de la méthode addPupil, nous passons un objet eleve en argument.
               
                $manager1->addSportEleve($sportEleve);

            } 
        }
}