IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

[POO] Passage de procédural à POO -> des questions


Sujet :

Langage PHP

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 40
    Par défaut [POO] Passage de procédural à POO -> des questions
    Bonsoir,

    Voilà je me suis mis à la POO sous PHP.
    Pour mettre en oeuvre tout ça je reprend un programme que j'avais écrit qui gère du matériel.

    Dans ma base de données j'ai une table materiel qui contient une dizaine d'infos par enregistrement : les enregsitrements sont identifiés par un deviceID

    J'ai écrit ma classe materiel : l'instance de l'objet impose de passer en paramètre un deviceID. Dans le constructeur j'ai placé mon accès à la base données qui extrait dans des variables private l'ensemble des champs concernés par ce deviceID.

    J'ai créé derrière mes méthodes "get" afin de pouvoir demander les champs qui m'interessent (getNum_Serie(), getConstructeur(), etc.) mais aussi des méthodes du type Sous_Garantie(), AgeMateriel(), etc.

    Bon jusque là ça va bien, dans mon ancien programme j'ai placé mes instances et me méthodes : ça roule.


    Là où je coince et là j'ai besoin de vous pour savoir comment je dois m'y prendre.
    Dans mon ancien programme j'ai une requête du type ci-dessous qui me retourne la liste du matériel d'un client :

    SELECT * FROM materiel WHERE clientid = '$clientid' and type = 'MICRO' ORDER BY num_serie


    Derrière cette requête j'ai une boucle do - while qui me permet de dessiner mon tableau de résultat.

    Je peux très bien me dire que je remplace au sein de la boucle mes champs de résultat de cette requête par des champs extraits d'une instance de ma classe materiel mais voilà : ça veut dire que pour 10 matériels je vais faire 10 requêtes SQL alors qu'avant je n'en avais qu'une ....

    Je me vois mal faire ça : c'est un retour en arrière. Des avis ?

  2. #2
    Membre expérimenté

    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    191
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 191
    Par défaut
    Hum, bon ca risque de grincé des dents.
    concernant les requetes sql je vois pas trop l'intéret d'utilisation d'objet car le hic c'est qu'on peut pas en faire grand chose, enfin sauf si quelqu'un a une méthode sans boucle pour obtenir un objet avec ces getters.

    en dehors de ca, développer en POO est clairement très puissant pour le traitement surtout si tu comprend l'utilisation du patern decorator (principe de brique).

    pour ma part j'ai créer un objet item qui prend un array en constructeur correspondant à la ligne sql retourné, une méthode getProperty(name) pour retourner la case name de l'array ca peut paraitre con mais c'est dans le cas ou je voudrai faire un traitement sur la propriété ou encore retourné une erreur. bon faut dire que j'ai aussi un setter de propriété ce qui fait que dans la classe d'accès à la DB je reçoit ou j'envoie un item rien de plus

    bref la POO très intéressant dans le traitement, honnêtement je dirai même excellent.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 40
    Par défaut
    pour ma part j'ai créer un objet item qui prend un array en constructeur correspondant à la ligne sql retourné
    Pas bête mais dans mon cas la requête me retourne plusieurs résultats.
    Sinon mon constructeur est construit un peu de la même manière : dans mon code j'instancie ma classe en lui passant en paramètre l'id de mon matériel.
    La classe construit son objet à partir de cette information.

    Dans le cas de résultats multiples : je peux très bien instancier mon objet à chaque tour de boucle mais ça veut dire que mon instance va provoquer une requête à chaque tour pour construire mon objet : ça marche mais je suis sur que l'on peut faire mieux.


    Pour moi (corrigez moi si je me trompe) : un objet ne contient qu'une valeur par attribut. A moins de construire l'objet à partir de valeure d'une requête directement depuis le code et non plus dans la classe pour éviter une requête à chaque instance.

    Faire ça avec un objet avec 5 attributs ça va mais avec 25 ....

  4. #4
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut
    Je procède souvent de la manière suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    class materiel
    {
    	public function __construct($id=null)
    	{
    		if(!empty($id))
    		{
    			//Requete sur matériel spécifique + remplissage champs privé
    		}
    	}
     
    	public function getMateriels($idClient)
    	{
    		//Requete sql adéquate
    		return $arrayMateriel
    	}
    }
    Ainsi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $materiel = new Materiel(5);
    te donnera accès à toutes les propriété d'un objet en particulier
    Et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $materiel->getMateriels(5)
    te retourneras un tableau de tous le materiel du client 5.

    C'est pas la solution la plus prorpe techniquement mais elle à le mérite d'être relativement simple.
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 40
    Par défaut
    Merci, c'est en effet une solution simple
    Mais on perd l'utilisation des méthodes comme celle déterminant l'état de la garantie, à moins d'inclure ces infos dans l'array retourné. Mais inclure ces infos c'est utiliser des fonctions car je vais me retrouver avec des traitements identiques à pleins d'endroits et ça va vite devenir une usine à gaz non maintenable.

    Je me demande si la solution n'est pas :

    - soit d'instancier mon objet en lui passant en paramètre tous les attributs (tant pis pour la lourdeur de la syntaxe si j'ai beaucoup d'attributs pour cette création)

    - soit d'instancier l'objet à chaque tour de boucle : plus propre et correspondant bien à l'idée de l'utilisation de "l'objet", mais plus lourd pour mon serveur SQL (enfin je pense -> 10 requêtes retournant 1 ligne sont peut être équivalentes à 1 requêtes retournant 10 lignes ?)

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 40
    Par défaut
    Je crois que j'ai trouvé !

    En parcourant le net j'ai vu de tout : des classes avec des attributs en public, facile à utiliser dans le code mais pas franchement recommandé pour respecté l'utilisation correcte des classes.
    De là j'ai appris ce qu'était des "getters" et "setters" et c'est de là que je tire ma solution !


    En utilisant le principe de Grunk pour l'instance : avec ou sans ID je n'ai plus que, dans le cas du sans ID, à utiliser des setters !

    Dans le cas d'un objet à instancier pour un ID : $materiel = new Materiel(5); (5 étant l'id du matériel).

    Dans le cas de ma boucle : avant le début de la boucle j'instancie mon objet : $materiel = new Materiel();

    Dans ma boucle j'utilise des setters : setDeviceID(), setDesignation(), setNumSerie(), etc.

    Et hop mon objet est utilisable avec toutes ses méthodes : getGarantie(), getAgeMateriel(), etc.


    Maintenant que je goute à l'objet sous PHP et que j'en comprend bien l'utilisation je ne suis pas prêt à revenir en arrière !! Le code est tellement plus propre et ça facilite tellement la vie une fois la classe bien écrite.

    Je vais mettre en oeuvre tout ça (j'ai du boulot mon appli PHP n'est pas petite et la ré-écrire en passant à l'objet demande pas mal de temps) et je reviens vous dire si cela fonctionne bien Merci pour votre aide.

  7. #7
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par défaut
    Bonjour messieurs

    Citation Envoyé par Helfima Voir le message
    Hum, bon ca risque de grincé des dents.
    concernant les requetes sql je vois pas trop l'intéret d'utilisation d'objet car le hic c'est qu'on peut pas en faire grand chose, enfin sauf si quelqu'un a une méthode sans boucle pour obtenir un objet avec ces getters.
    Hé bien envisagez sérieusement de vous mettre à utiliser un moteur d'ORM comme Doctrine par exemple car ces outils font typiquement tout ce sale boulot à votre place (et sûrement bien mieux que si vous codiez vous même les requêtes).

    A+

  8. #8
    Membre Expert
    Avatar de ThomasR
    Homme Profil pro
    Directeur technique
    Inscrit en
    Décembre 2007
    Messages
    2 230
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 2 230
    Par défaut
    Bonjour,


    Je peux très bien me dire que je remplace au sein de la boucle mes champs de résultat de cette requête par des champs extraits d'une instance de ma classe materiel mais voilà : ça veut dire que pour 10 matériels je vais faire 10 requêtes SQL alors qu'avant je n'en avais qu'une ..
    C'est beaucoup plus simple que ca, tu dois pouvoir instancier ton objet à partir d'un tableau, comme çà tu ne fais qu'une seule requête ! Un peu comme le fais Grunk.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    class materiel{
        private $id_materiel, $nom;
     
        public function __construct($defaultId = -1){
            $this->id_materiel = $defaultId;
        }
     
        public static function fromArray(array $fields){
            $m = new materiel(intval($fields['id_materiel']));
            $m->setNom($fields['nom']);
            return $m;
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    $conn = SqlConnection::instance();
    $query = $conn->query('SELECT * FROM materiels ORDER BY nom ASC');
    $materiels = array();
    while($row = $conn->fetchArray($query)){
        array_push($materiels, materiel::fromArray($row));
    }
     
    print_r($materiels);
    Aussi, une méthode telle que "getMateriels" ne doit pas être intégrée au sein de la classe materiel, cela n'a pas de sens (un matériel ne possède pas de matériels..). Elle doit être implémentée au sein d'un provider de materiels, ou d'un provider plus global, dont l'instance est unique ou au travers d'une méthode statique.

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 40
    Par défaut
    Merci pour votre réponse
    Je ne savais pas que l'on pouvait retourner un objet depuis une méthode.

    Ca revient en gros à ma solution énoncée plus haut mais au lieu de à chaque fois écrire mes "setters" je le fais une bonne fois pour toute au sein d'une méthode ! Diablement efficace ça

    De même si j'ai bien compris tu stock les objets dans un array ?
    Merci de votre indulgence, je suis amateur et pas professionnel : j'apprends sur le tas



    EDIT : après test en effet ça fonctionne, on récupère bien un array de valeures provenant de l'objet en un seule requête.
    Mais cela ne me permet pas d'utiliser l'objet $m ainsi créé (car créé dans la classe) :/

    Par contre je peux très bien imaginé d'instancier mon objet en passant systématiquement un array au constructeur : plus de requête au sein du constructeur de mon objet. Résultat ça m'ouvre diverses utilisation.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
     // Méthodes    
     
      public function __construct (array $fields) // Constructeur 
            {
     
     
    		   $this->deviceid = $fields['deviceid'];
    		   $this->clientid = $fields['clientid'];
    		   $this->designation = $fields['designation'];
    		   $this->type = $fields['type'];
    		   $this->num_serie = $fields['num_serie'];
    		   $this->ref_constructeur = $fields['ref_constructeur'];
     
     
     
     
            }

    Là au moins ça répond à toutes mes utilisations

  10. #10
    Membre Expert
    Avatar de ThomasR
    Homme Profil pro
    Directeur technique
    Inscrit en
    Décembre 2007
    Messages
    2 230
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 2 230
    Par défaut
    De même si j'ai bien compris tu stock les objets dans un array ?
    Oui, mais tu pourrais les stocker dans un SplObjectStorage également si tu souhaites gérer une réelle collection.

  11. #11
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par défaut
    Bonjour

    Et avec un moteur d'ORM, les getters/setters et autres "fromArray" sont générés automatiquement, ainsi que toutes les requêtes, 0 lignes à écrire à la main

    C'est sûr, pour un débutant, cela a un coût d'apprentissage, mais vous gagnerez par la suite un temps faramineux. Je ne puis que vous le conseiller plus que vivement.

    Cordialement

  12. #12
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 40
    Par défaut
    Citation Envoyé par ThomasR Voir le message
    Oui, mais tu pourrais les stocker dans un SplObjectStorage également si tu souhaites gérer une réelle collection.
    J'ai édité mon message plus haut.

    Si vous pouvez me confirmer si j'ai bien compris :

    Dans votre code on a bien les valeures de l'objet dans une table mais pas l'objet en lui même ?
    Mon but est d'utiliser dans ma boucle des méthodes donc besoin de l'objet (à moins de n'avoir pas bien compris le rôle d'un objet je trouve ça bête de juste en utiliser les valeurs : pour cela il me suffit de simplement prendre les valeures dans le résultat de la requête).

    Pour moi mon objet Materiel représent 1 Matériel avec des propriétés et des méthodes que je souhaite utiliser au sein de ma boucle.

  13. #13
    Membre Expert
    Avatar de ThomasR
    Homme Profil pro
    Directeur technique
    Inscrit en
    Décembre 2007
    Messages
    2 230
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 2 230
    Par défaut
    Citation Envoyé par Falconpage Voir le message
    Si vous pouvez me confirmer si j'ai bien compris :
    Dans votre code on a bien les valeures de l'objet dans une table mais pas l'objet en lui même ?
    Oui, cela permet de conserver une architecture des données conforme à l'objet que vous souhaitez représenter.

    Ensuite, et c'est logique, l'objet doit pouvoir être instancié depuis son état en base de données, d'où la fonction statique materiel::fromArray(array $fields);
    Citation Envoyé par Falconpage Voir le message
    Mon but est d'utiliser dans ma boucle des méthodes donc besoin de l'objet (à moins de n'avoir pas bien compris le rôle d'un objet je trouve ça bête de juste en utiliser les valeurs : pour cela il me suffit de simplement prendre les valeures dans le résultat de la requête).

    Pour moi mon objet Materiel représente 1 Matériel avec des propriétés et des méthodes que je souhaite utiliser au sein de ma boucle.
    Si tu souhaites parcourir une liste de matériel et pour chacun d'eux faire un traitements :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    class materiels{
        private static $all;
        public static function getAll(){
            if(self::$all === NULL){
                $conn = SqlConnection::instance();
                $query = $conn->query('SELECT * FROM materiels ORDER BY nom ASC');
                self::$all= array();
                while($row = $conn->fetchArray($query)){
                    array_push(self::$all, materiel::fromArray($row));
                }
            }
            return self::$all;
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    $materiels = materiels::getAll();
    foreach($materiels as $i => $materiel){
        echo $i . ' : ' . $materiel->getNom();
    }
    Tu remarqueras le lazy-loading des materiels dans la fonction materiels::getAll afin de ne pas faire deux fois la requête et l'instanciation si tu en as besoin plusieurs fois dans ta page.

  14. #14
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 40
    Par défaut
    J'ai opté pour le moment pour l'utilisation d'un constructeur basé sur l'id d'un matériel qui me construit mon objet en entier en executant une requête au sein de mon constructeur.
    J'ai laissé la possibilité d'instancier l'objet sans ID

    Pour ma boucle, depuis le code j'instancie l'objet sans ID (avant la boucle), derrière je passe la méthode FromArray (dans la boucle) qui set les atttribus au sein de mon objet (sans return).

    Je peux ainsi utiliser mes méthodes dans la boucle : GetGarantie, etc.

    Mon objet répond ainsi à mes deux exigences

  15. #15
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 40
    Par défaut
    ThomasR, merci pour votre dernière réponse
    Je vais étudier votre code avec attention.

  16. #16
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 40
    Par défaut
    Bonsoir,

    Désolé du retard pour la réponse.
    Juste un petit mot pour vous dire que ça fonctionne impec :

    Si je passe un id en paramètre lors de l'instance de l'objet celui-ci se contruit à partir d'une requête pour setter mes propriétés.

    Si je ne passe rien en paramètre alors l'objet est instancié simplement.
    J'appelle une méthode spécifique qui set les propriétés à partir d'un array passé en paramètre.

    Pour ma boucle do-while : j'instancie l'objet avant le do et dans la boucle j'appelle ma méthode, sachant qu'à chaque tour mon array évolue donc mon objet aussi. Je peux donc utiliser mes différentes méthodes au sein de la boucle (getGarantie, getAgeMateriel, etc.) sans requête

    Merci pour votre aide.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. POO: Passage par référence, question technique.
    Par FMaz dans le forum Langage
    Réponses: 7
    Dernier message: 07/05/2009, 20h04
  2. [POO] sauvegarde d'objets et perte des methodes
    Par Matth_S dans le forum Langage
    Réponses: 3
    Dernier message: 23/12/2005, 15h47
  3. [POO] Passage d'objet dans un formaulaire
    Par jiluc dans le forum Langage
    Réponses: 4
    Dernier message: 16/12/2005, 16h07
  4. [POO] passage nom objet dsn les parametres d'une fonction
    Par melou dans le forum Général JavaScript
    Réponses: 12
    Dernier message: 21/10/2005, 17h26
  5. Réponses: 3
    Dernier message: 17/10/2005, 16h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo