Partage
  • Partager sur Facebook
  • Partager sur Twitter

Site eCommerce PHP

Appeler une fonction readAll dauns une classe métier Manager

    13 août 2018 à 9:46:50

    Bonjour à toutes et à tous!

    je suis actuellement à l'AFPA en tant que développeur logiciel

    J'ai un problème pour afficher les données de ma fonction readAll(){}

    J'ai crée mon service DAO, ainsi que mes classesManager qui y sont jointes. 

    <?php
    
    class Clients
    {
    	//getters et setters de l'id
    	private $numcli;
    	public function getNumcli()
    	{
    		return $this->numcli;
    	}
    
    	public function setNumcli($v)
    	{
    		$this->numcli=$v;
    	}
    	
    
    	//de telcli
    	private $telcli;
    	public function getTelcli()
    	{
    		return $this->telcli;
    	}
    
    	public function setTelcli($v)
    	{
    		$this->telcli=$v;
    	}
    	
    	//de nomcli
    	private $nomcli;
    	public function getNomcli()
    	{
    		return $this->nomcli;
    	}
    
    	public function setNomcli($v)
    	{
    		$this->nomcli=$v;
    	}
    
    	//de adrcli
    	private $adrcli;
    	public function getAdrcli()
    	{
    		return $this->adrcli;
    	}
    
    	public function setAdrcli($v)
    	{
    		$this->adrcli=$v;
    	}
    	/*
    	//Je crée mon constructeur
    	public function __construct($numcli,$telcli,$nomcli,$adrcli)
    	{
    		$this->numcli=$numcli;
    		$this->telcli=$telcli;
    		$this->nomcli=$nomcli;
    		$this->adrcli=$adrcli;
    <?php 
    require_once ("SGBDConnection.php");
    require_once ("Clients.php");
    
    class ClientManager
    {
    	public function read($key)
    	{
    		$response=SGBDConnection::getConnection()->prepare(
    			"select * from clients where numcli=?;");
    		$response->execute(array($key));
    		$client=new Clients();
    		while($donnees=$response->fetch())
    		{
    			$client->setNumcli($donnees['numcli']);
    			$client->setTelcli($donnees['telcli']);
    			$client->setNomcli($donnees['nomcli']);
    			$client->setAdrcli($donnees['adrcli']);
    
    
    		}
    
    		$response->closeCursor();
    
    		return $client;
    	}
    
    	public function readAll()
    	{
    		$resultat=array();
    		$response=SGBDConnection::getConnection()->prepare(
    			"select * from clients;");
    		$response->execute(array());
    		while($donnees=$response->fetch())
    		{
    			$client=new Clients();
    			$client->setNumcli($donnees['numcli']);
    			$client->setTelcli($donnees['telcli']);
    			$client->setNomcli($donnees['nomcli']);
    			$client->setAdrcli($donnees['adrcli']);
    
    			array_push($resultat, $client);
    
    		}
    		$response->closeCursor();
    
    		return  $resultat;
    	}
    }
    
    ?>
    <?php
    
    class SGBDConnection {
        
        const DB = 'mysql:host=localhost;dbname=maintinfo;charset=utf8';
        private static $user = "root";
        private static $pass = "";
    
        private static $connection = NULL;
        
        private function __construct() {}
        
        public static function getConnection() {
            if (SGBDConnection::$connection== null) 
            {
                try 
                {
                    
                SGBDConnection::$connection = new PDO(SGBDConnection::DB, SGBDConnection::$user, SGBDConnection::$pass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
                } 
                catch ( Exception $e ) 
                {
                    echo "Erreur ". $e->getMessage () . "<br/>";
                    print_r(SGBDConnection::$connection->errorInfo()) ;
                    die("Connexion Echoue") ;
                }
    
    		}
            return SGBDConnection::$connection;
        }
    
    }
    <?php 
    require_once 
    ('../modele/SGBDConnection.php');
    require_once
    ('../modele/Clients.php');
    require_once
    ('../modele/ClientManager.php');
    
    ?>
    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="ISO-8859-1">
    	<title>Table des clients</title>
    	  <!-- Bootstrap core CSS -->
        <link href="../bootstrap/css/bootstrap.min.css" rel="stylesheet">
    
        <!-- Custom styles for this template -->
        <link href="style.css" rel="stylesheet">
    </head>
    <body>
    <form>
    
    	Liste des clients:</br>
    	<table>
    
    		<tr>
    			<th>Numéro</th>
    			<th>Téléphone</th>
    			<th>Nom</th>
    			<th>Adresse</th>
    		</tr>
    
    	<?php
    		//J'aimerais afficher les données du readAll de ClientManager??
    		?>
    	</table>
     
     




    • Partager sur Facebook
    • Partager sur Twitter
      13 août 2018 à 12:41:29

      Hello,

      Autant le dire tout de suite, je ne suis pas du tout un habitué de cette méthode de travail en tout POO avec une telle organisation. Cependant je remarque plusieurs trucs qui me chiffonnent :

      • read(key) et readAll() présentent une grosse duplication de code qui paraît inadaptée
        En effet, dès qu'il y a un passage "copié/collé" dans du code, c'est qu'il y a un problème de conception
        En l'occurrence il serait logique d'avoir un truc de type getAll() qui te donnerait un tableau de l'ensemble des ID
        Ensuite, tu pourrais simplement appliquer ta méthode read(key) à chaque ID du tableau...

      • Ceci étant réglé reste une question "épineuse" pour moi : que faire de ton "tas" d'objets ?
        Si on suit cette logique et que l'on veut coller à ce que tu cherches à faire, il faut que readAll() te renvoie un "paquet" d'objets
        Problème, j'ai aucune idée de comment on fait pour créer un objet qui contient d'autres objets... si ce n'est par une classe
        D'ailleurs je pense que c'est obligatoire dans la mesure où tu veux côté vue pouvoir les prendre un par un (foreach ?)
        Il me semble me souvenir que pour que ce soit possible, il faut que la classe de ton "paquet" implémente Iterator
        http://php.net/manual/fr/class.iterator.php

      • Une fois que tu arrives à régler ça...
        D'abord il faut ouvrir le tableau et mettre en place les entêtes...
        Tu arrives à ton objectif, c'est à dire être en capacité de faire un foreach sur un objet qui te répond avec une ligne
        Pour chaque ligne tu peux construire la suite de ton tableau... en ajoutant une ligne et les infos qui vont bien
        Une fois terminé tu fermes ton tableau...

      Désolé de pas être d'une meilleure aide, j'essaye de donner simplement des pistes étant donnée ma méconnaissance de ce type de procédé, qui est toutefois bien intéressant...

      Peut-être une piste ici, bien qu'un peu ancienne : https://sony-noel.developpez.com/tutoriels/php/collection-objet-avec-php/

      Autre piste : sérialiser les objets clients et les ranger dans un tableau classique... Quand tu fais le foreach, tu unserialize et voilà ? ... C'est sans doute beaucoup plus simple... ?

      -
      Edité par Nicolas B 13 août 2018 à 12:46:28

      • Partager sur Facebook
      • Partager sur Twitter
      Nicolas - Développeur PHP qui bricole pas mal, utilisant Bootstrap, Materialize, MySQL et quelques astuces piochées par ci par là. Codeigniter a changé ma vie de codeur :D
        13 août 2018 à 15:58:39

        Bonjour,

        J'ai remarqué de mon côté aussi que tu utilisai le pattern Singleton pour la connexion à la DB. Je pense que le mieux reste l'injection de dépendances car cela rends le code plus flexible (surtout si on passe par des interfaces). Voici le code que j'aurais fait qui représente ma vision à moi et qui n'est pas parfaite pour un exemple aussi petit.

        Fichier de la vue :

        <?php
        
        // Il faudra passer par un autoloader plus tard 
        require __DIR__ . '/src/PdoConnection.php';
        require __DIR__ . '/src/Hydratable.php';
        require __DIR__ . '/src/Client.php';
        require __DIR__ . '/src/Client.php';
        
        $db = new PdoConnection('mysql:host=localhost;dbname=maintinfo;charset=utf8', 'root', '');
        $clientsManager = new ClientsManager($db);
        
        $clients = $clientsManager->all();
        
        ?>
        <!DOCTYPE html>
        <html lang="fr">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport"
                  content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
            <meta http-equiv="X-UA-Compatible" content="ie=edge">
            <meta name="author" content="quenti77">
            <title>OCR</title>
        </head>
        <body>
            <form action="view.php" method="post">
                <table>
                    <thead>
                    <tr>
                        <th>Numéro</th>
                        <th>Téléphone</th>
                        <th>Nom</th>
                        <th>Adresse</th>
                    </tr>
                    </thead>
                    <tbody>
                    <?php foreach ($clients as $client): ?>
                        <tr>
                            <td><?= $client->getNumcli() ?></td>
                            <td><?= $client->getTelcli() ?></td>
                            <td><?= $client->getNomcli() ?></td>
                            <td><?= $client->getAdrcli() ?></td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
            </form>
        </body>
        </html>
        <?php
        
        /**
         * Class PdoConnection
         */
        class PdoConnection extends PDO
        {
            /**
             * PdoConnection constructor.
             * @param string $dsn
             * @param string $username
             * @param string $passwd
             * @param array $options
             */
            public function __construct(string $dsn, string $username, string $passwd, array $options = [])
            {
                parent::__construct($dsn, $username, $passwd, $options);
        
                // Il te manque aussi les options comme la gestion des exceptions
                parent::setAttribute(parent::ATTR_DEFAULT_FETCH_MODE, parent::FETCH_ASSOC);
                parent::setAttribute(parent::ATTR_ERRMODE, parent::ERRMODE_EXCEPTION);
            }
        
            /**
             * Version basique. Si tu veut une version plus
             * pousser je peux te passer le lien de mon fichier sur github
             *
             * @param string $statement
             * @param array $params
             * @return PDOStatement
             */
            public function request(string $statement, array $params = []): PDOStatement
            {
                $request = $this->prepare($statement);
                $request->execute($params);
        
                return $request;
            }
        }
        
        <?php
        
        /**
         * Pour éviter le DRY de chaque entité je créé un trait
         *
         * Trait Hydratable
         */
        trait Hydratable
        {
            /**
             * @param array $data
             */
            public function hydrate(array $data = []): void
            {
                foreach ($data as $key => $value) {
                    $methodName = 'set'.ucfirst($key);
        
                    if (method_exists($this, $methodName)) {
                        $this->$methodName($value);
                    }
                }
            }
        }
        
        <?php
        
        /**
         * Class Client
         * Au singulier vu que l'on ne gère qu'un client par objet
         *
         * Aussi si ta table s'appel clients pas besoin
         * que chaque champ est un suffixe. Essaye de pas faire ce que
         * l'on appel du DRY (pour Don't Repeat Yourself)
         */
        class Client
        {
            use Hydratable;
        
            /**
             * id à la place de numCli ?
             * @var int $numcli
             */
            private $numcli;
        
            /**
             * @var string $telcli
             */
            private $telcli;
        
            /**
             * @var string $nomcli
             */
            private $nomcli;
        
            /**
             * @var string $adrcli
             */
            private $adrcli;
        
            /**
             * Client constructor.
             * @param array $data
             */
            public function __construct(array $data = [])
            {
                $this->hydrate($data);
            }
        
            /**
             * @return int
             */
            public function getNumcli(): int
            {
                return $this->numcli;
            }
        
            /**
             * @param int $numcli
             */
            public function setNumcli(int $numcli): void
            {
                $this->numcli = $numcli;
            }
        
            /**
             * @return string
             */
            public function getTelcli(): string
            {
                return $this->telcli;
            }
        
            /**
             * @param string $telcli
             */
            public function setTelcli(string $telcli): void
            {
                $this->telcli = $telcli;
            }
        
            /**
             * @return string
             */
            public function getNomcli(): string
            {
                return $this->nomcli;
            }
        
            /**
             * @param string $nomcli
             */
            public function setNomcli(string $nomcli): void
            {
                $this->nomcli = $nomcli;
            }
        
            /**
             * @return string
             */
            public function getAdrcli(): string
            {
                return $this->adrcli;
            }
        
            /**
             * @param string $adrcli
             */
            public function setAdrcli(string $adrcli): void
            {
                $this->adrcli = $adrcli;
            }
        }
        
        <?php
        
        class ClientsManager
        {
            /**
             * @var PdoConnection $connection
             */
            private $connection;
        
            public function __construct(PdoConnection $connection)
            {
                $this->connection = $connection;
            }
        
            /**
             * Client[] c'est pour dire à l'ide que c'est
             * un tableau de type Client. PHP ne le comprendra pas.
             *
             * @return Client[]
             */
            public function all(): array
            {
                $result = [];
        
                // La je vais me répéter au niveau de la requête mais
                // je vais pas faire tout un système de requête
                // Aussi on évite de mettre * d'habitude
                $response = $this->connection->request('SELECT * FROM clients');
        
                foreach ($response as $client) {
                    $result[] = new Client($client);
                }
        
                return $result;
            }
        
            /**
             * @param int $numcli
             * @return Client|null
             */
            public function findByNum(int $numcli): ?Client
            {
                $response = $this->connection->request('SELECT * FROM clients WHERE numcli = :numcli', [
                    ':numcli' => $numcli
                ]);
        
                $result = $response->fetch();
                if ($result) {
                    return new Client($result);
                }
        
                return null;
            }
        }
        

        Cela fait beaucoup de ligne mais il y a les commentaires de documentation que je t'encourage à faire.

        • Partager sur Facebook
        • Partager sur Twitter
          13 août 2018 à 21:56:57

          Je surkiffe la propreté de ton code ! :waw::magicien:
          • Partager sur Facebook
          • Partager sur Twitter
          Nicolas - Développeur PHP qui bricole pas mal, utilisant Bootstrap, Materialize, MySQL et quelques astuces piochées par ci par là. Codeigniter a changé ma vie de codeur :D
            14 août 2018 à 15:49:36

            Bonjour à vous 2!

            Tout d'abord merci Nicolas B. Je vois que tu n'as pas l'air d'être un adepte du modèle MVC??!! Lol.

            Et je tiens tout de même à te remercier pour l'effort fourni.

            Quenti77, merci à toi aussi. Seulement, je ne suis pas un adepte de la méthode hydrate. A vrai dire, je l'ai survolé en regardant le tuto OpenClassrooms.

            Aussi, quand tu parles d'"autoload", tu parles aussi de l'installation de "composer"? Pour l'instant, je fais une version simpliste MVC. Nous avons eu 1 semaine de cours sur PHP, mySQL, HTML, CSS.

            J'ai encore du mal à maîtriser et je ne pense pas avoir le temps de faire le tuto OpenClassrooms. 

            Je reviendrai vers vous une fois que j'aurai compris ton code.

            Merci encore :)

            • Partager sur Facebook
            • Partager sur Twitter
              14 août 2018 à 16:17:44

              Composer serait en effet un plus et plus simple à mettre en place en étant plus performant mais se créer un autoloader n'est pas très compliquer et t'évitera des require fait à la mano. Cela évite aussi de charger des fichiers pour rien.

              Tu peux passer par autre chose qu'un hydrator mais en aucun cas si ta table à 20 champs (ce qui arrive plus souvent qu'on le pense) tu va avoir 20 paramètres dans ton consutructeur. Avec l'hydratation comme dans le cours ou comme j'ai fait, cela permet déjà de 1 d'avoir qu'un tableau à passer. Et en plus si tu veux ajouter un champs c'est simple, il suffit de faire l'attribut privée, le getter et le setter et c'est bon. En plus de ça des IDE comme phpstorm ou un plugin dans ton éditeur te permettra de le générer automatiquement.

              En plus de ça si tu veux fournir que le nom et le numero de tel sans l'id et l'adresse tu peux plus facilement avec un tableau qu'avec des paramètres à la suite :

              function user1($id = null, $nom = null; $adr = null, $tel = null)
              {
                  $this->id = $id;
                  // etc.
              }
              
              function user2($data = [])
              {
                  $this->hydrator($data);
              }
              
              // Je ne veux que nom et tel
              user1(null, 'nom', null, 'tel');
              user2([ 'nom' => 'nom', 'tel' => 'tel']);


              Enfin dernière chose aussi. L'hydrator que j'ai mis est le même pour TOUS tes models. Alors que tu devra faire un constructor différent par model.

              Après si tu dev depuis peu c'est pas grâve si tu comprends pas tout de mon code ou si tu fais de la mauvaise POO car en vrai même moi qui en fait depuis longtemps, il y a surement des trucs que je fais encore mal en POO.

              -
              Edité par quenti77 14 août 2018 à 16:19:23

              • Partager sur Facebook
              • Partager sur Twitter
                15 août 2018 à 23:07:01

                Si, je suis évidemment passé au MVC depuis un moment même si sur mes projets persos je m'autorise parfois quelques libertés (et notamment mélanger un peu souvent le contrôleur et le modèle, parce qu'isoler une requête SQL du contrôleur juste pour 2 lignes, ça me soule... et parfois j'ai tendance à préparer la transformation de certaines données reçues dans le contrôleur aussi avant d'envoyer les blocs html "finis" à la vue ce qui n'est pas forcément idéal).

                Par contre j'ai sauté une étape dans ma progression, en passant directement de mes "bricolages" maisons le plus souvent en procédural à la base... aux frameworks MVC comme CodeIgniter donc je suis devenu vraiment fan pour sa simplicité, pour le coup tout en POO. Donc en effet, dans ma pratique quotidienne je n'ai pas l'habitude de gérer ce genre de "détails" manuellement puisque j'utilise l'abstraction base de données fournie par CodeIgniter qui est très efficace et pratique et je n'ai donc jamais eu à écrire ce genre de trucs moi, à la main from scratch.

                Voilà pour la liste de mes imperfections si jamais ça te faisait mieux comprendre l'esprit de ma réponse ^^

                • Partager sur Facebook
                • Partager sur Twitter
                Nicolas - Développeur PHP qui bricole pas mal, utilisant Bootstrap, Materialize, MySQL et quelques astuces piochées par ci par là. Codeigniter a changé ma vie de codeur :D

                Site eCommerce PHP

                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                • Editeur
                • Markdown