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 :

Variable indéfinie, class [PHP 5.3]


Sujet :

Langage PHP

  1. #1
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 051
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 051
    Points : 1 638
    Points
    1 638
    Par défaut Variable indéfinie, class
    Bonjour,

    Je suis en train de développer un site web et je rencontre un petit soucis avec mes classes PHP.

    J'obtiens une erreur que ma variable $connexion n'est pas défini.

    Voici le code

    connexionBDD2.php:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <?php
     
    $connexion = new mysqli('localhost', 'nom_user', '');
    $connexion->select_db('nom_BDD') or die("erreur");
     
    ?>
    class covoiturage.php
    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
    19
    20
    21
    22
    23
    24
    class covoiturage
    	{
    		private $AllCovoiturage = array();
     
    		function __construct()
    		{
     
    		}
     
    		function Create()
    		{
                    	include("../../connexion/connexionBDD2.php");
    			$AddCovoiturage = "INSERT INTO covoiturage(// Liste des paramètres												  ) 
     VALUES (//Liste des paramètres)";
    			$reussi = $connexion->query($AddCovoiturage) or die ("Erreur creation ");
                            // Boucle pour implémenter l'array AllCovoiturage
    			if($reussi)
    				echo "<script language='JavaScript'>alert('Votre trajet a bien été créé. Vous le retrouverez dans la section covoiturage ou dans votre profil.')</script>";
                    mysqli_close($connexion);
                    return $this->AllCovoiturage;
                    }
     
      // Plusieurs méthodes du même genre
            }
    class profil.php
    Le code est identique, un constructeur vide, une requete insert avec un return d'un array dans chaque fonction.

    Et dans le code appelant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $Init = new covoiturage();	
    $P = new profil();		
    $tableau = $Init->Create();
    $P = $Init->RetourProfil();
    Et là sur l'appel de la fonction RetourProfil, il me dit que ma variable $connexion de ma class n'est pas défini "error call member is non object" ou un message d'erreur de ce genre.

    Par contre si je supprime la création de l'objet covoiturage() et la méthode appelé Create() ca fonctionne.

    Il peut y avoir des conflits entre méthodes ? Pourquoi ma 2eme variable $connexion n'est pas défini ?

    J'ai essayé de simplifié au maximum le code, j'espère que ca suffira.

    Merci !!

  2. #2
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Bonjour,

    En gros ce que tu dis, c'est qu'à chaque fois que tu as besoin d'une connexion tu insères ton fichier connexionBDD2.php qui lui ouvre à chaque fois une nouvelle connexion new mysqli(). Euh c'est bancal. Tu avoueras qu'il serait préférable de n'utiliser qu'une seule et unique connexion pour toutes tes requêtes, non ? Si tu es de cet avis, regarde du côté d'un Singleton.
    Pour ton erreur, il faudrait regarder du côté des logs php.
    Est-ce que les fichiers profil.php et covoiturage.php sont dans le même répertoire ?

  3. #3
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 051
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 051
    Points : 1 638
    Points
    1 638
    Par défaut
    Bonjour,

    Oui en effet j'inclus à chaque fois mon fichier de connexion car je ne savais pas comment faire autrement :s Je vais regarder du coter des singleton

    Sinon oui toutes mes classes sont dans le même dossier, j'ai une architecture standard je pense :
    Dossier principale
    dossier class
    dossier pages
    dossier js
    ....

    En fait, dès que j'utilise deux objets de deux classes différentes dans la même page, ca me renvoi cette erreur. Jusqu'à présent je me débrouillais pour en utiliser qu'une par page, mais il doit y avoir une raison .. si c'est ma façon de coder faut le dire, je début en PHP objet

  4. #4
    Membre expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Points : 3 947
    Points
    3 947
    Par défaut
    ... si c'est ma façon de coder faut le dire ...
    Oui, et non.

    En fait, tu rencontre des problème de portées, de visibilité, sur certaines variable (ou Objet, peu importe).
    Ceci n'est pas propre à l'Objet, c'est la même chose en procédural (ou classique).

    Par défaut, une variable n'est pas "visible", dans une fonction, même chose dans une méthode de classe.
    A moins de la déclarer "globale" dans la fonction ou méthode de classe, ou encore de la "passer" en paramètre, de créer une méthode statique, voir autre ...



    En faite, le vrai fond du problème que tu rencontres c'est qu'auparavant tu utilisais très certainement les fonctions mysql_*.
    C'est ce cas là qui est (très) particulier, et non le cas actuel qui lui est normal.
    En exploitant ces fonctions, plus particulièrement lorsqu'on crée une connexion avec la fonction mysql_connect(), MySQL conserve en mémoire cette connexion.
    Du coup, si on exécute un mysql_query() dans une fonction, voire même dans une méthode de classe, il n'y a pas besoin de refaire une connexion.
    MySQL réutilise la dernière connexion effectuée, et cela automatique.
    C'est ce comportement là qui est particulier, qui rend les choses plus facile : On ne rencontre aucun de problème de portée.


    Avec un Objet MySQLi, même chose pour PDO, il n'y a plus cette (re)connexion automatique, il faut faire référence à cette connexion explicitement avec la variable ou Objet qui l'a contient (comme n'importe quelle variable d'ailleurs).


    Conclusion : En utilisant MySQLi tu reviens ni plus ni moins dans une situation normale.
    On ne peux pas exploiter une variable ou Objet non déclarée dans une fonction ou méthode de classe.
    Donc soit :
    - refaire une connexion (très lourd/répétition de code)
    - La passer en paramètre
    - la déclarer en globale (pas propre)
    - créer un singleton (c'est très certainement la technique la plus utilisée)
    - autres techniques encore que je connais pas ...


    Vois tu pourquoi tu rencontres ce problème actuellement ?

  5. #5
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 051
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 051
    Points : 1 638
    Points
    1 638
    Par défaut
    Merci pour les informations.

    En fait j'ai toujours utilisé mysqli pour les connexions, même quand je codais en procédurale.

    Quand l'erreur affiche que ma variable $connexion n'est pas défini, l'erreur s'affiche dans la class php et pas dans le programme principal.

    C'est l'appel dans le programme principal qui déclenche l'erreur (normal vu que la connexionBDD se fait dans chaque méthode).

    Je pense bien avoir compris cependant que mon erreur se situait au niveau des appels de ma connexion BDD.

    Cependant je vois pas pourquoi, même si je fais un appel à chaque fois, pourquoi au deuxième objet il me dit que ma variable $connexion n'est pas défini, peut-être parce cette variable a déjà était utilisé juste avant dans l'autre objet ? Mais je pensais que mysqli_close() fermait la connexion ainsi que "détruisait" le new mysqli() et donc le $connexion.

    Au niveau des portées des variables je sais à quoi ca correspond, mais là tout le soucis se passe dans les class je suppose .

  6. #6
    Membre expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Points : 3 947
    Points
    3 947
    Par défaut
    Evites de fermer la connexion.
    Normalement MySQL le fait automatiquement dès qu'on ne l'exploite plus, du coup c'est plus rapide de faire manuellement et successivement des connexions/déconnexions.

    Mise à par ça, quel est le code du 2ème Objet ?
    Est-ce qu'une connexion est faite ?

    Attention : Concernant les portées, si tu inclus dans une méthode le code qui effectue la connexion, ça ne veut pas dire que cette connexion soit visible dans une autre méthode.
    Il faut refaire une connexion dans la 2ème méthode. (une méthode c'est comme une fonction, ça a les mêmes spécificités).

    Du coup, au lieu d'inclure le fichier qui fait la connexion dans 1 seule méthode (comme covoiturage::Create), tu peux le faire dans le constructeur, puis la stocker dans une propriété de l'Objet.
    La propriété elle sera visible dans toutes les méthodes de la classe.
    Exemple :
    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 covoiturage {
        protected $connexion;
     
        public function __construct() {
            include("../../connexion/connexionBDD2.php");
            $this->connexion = $connexion;
        }
     
        public function Create() {
            // On exploite la propriété : connexion
            $reussi = $this->connexion->query($AddCovoiturage);
        }
    }
    Ceci dit, ce principe revient presque à déclarer $connexion en global (pas très zen comme principe).

    Penches toi sur la création d'une classe de connexion de MySQLi en singleton.
    Ca se résume à exploiter cette classe de cette manière (sans aucune inclusion)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        public function Create() {
            // SQLI étant la classe singleton
            $reussi = SQLI::Instance()->query($AddCovoiturage);
        }
    Toujours est il que je reste étonné que tu n'est pas rencontré ce problème avant (mode procédural) étant donné que tu utilisais déjà MySQLi.


    Au passage, dans ma doc de Php je ne vois pas de fonction mysqli_close(), juste le mode Objet, MySQLi::close().
    C'est à croire quelle n'existerait pas. (Je n'utilise pas MySQLi, mais PDO, donc j'en sais trop rien).
    T'as pas une erreur en appelant cette fonction ?

  7. #7
    Expert éminent
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Points : 7 762
    Points
    7 762
    Par défaut
    Citation Envoyé par RunCodePhp Voir le message
    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 covoiturage {
        protected $connexion;
     
        public function __construct() {
            include("../../connexion/connexionBDD2.php");
            $this->connexion = $connexion;
        }
     
        public function Create() {
            // On exploite la propriété : connexion
            $reussi = $this->connexion->query($AddCovoiturage);
        }
    }
    Un bel exemple de couplage en béton armé.

    Voici une alternative plus flexible:
    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 Covoiturage {
      /**
       * @var PDO
       */
      protected $_connection;
      public function __construct (PDO $connection) {
         if (!isset($connection))
           throw new InvalidArgumentException("First parameter is expected to be a valid PDO instance, null given");
         $this->_connection = $connection;
      }
      public function Create() {
        $reussi = $this->_connection->query(...);
      }
    }

  8. #8
    Membre expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Points : 3 947
    Points
    3 947
    Par défaut
    Citation Envoyé par Benjamin Delespierre
    Un bel exemple de couplage en béton armé.
    Le but n'était pas faire une démonstration du comment faire du béton armé (ça l'était déjà), mais de faire voir la différence entre inclure dans le constructeur et 1 seule méthode de classe, rien de plus.
    Le passage en paramètre c'est une tout autre technique, donc pas de comparaison possible.

    Mes explications n'étaient pas très clairs certainement.

  9. #9
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 051
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 051
    Points : 1 638
    Points
    1 638
    Par défaut
    Merci beaucoup en tout cas !

    Pour le moment, j'ai testé la version "temporaire" qui est de créer la connexion dans le constructeur et d'utiliser la variable protected partout, du coup j'ai plus qu'un seul include (honnêtement, en codant les méthodes, je trouvais ca très bof d'inclure la connexionBDD dans chacune ...) et ca semble fonctionner parfaitement.

    C'était donc le new mysqli() créé à chaque fois (et pour deux objets différents surtout) qui faisait bugger. Comme j'avais un objet qui utilisait ca.

    Sinon je vois pas trop la différence entre un singleton et une classe minimaliste
    Si je fais une class MyConnection() qui a un constructeur qui établit la connexion mysqli() puis une méthode qui renvoi cette variable. La création d'un singleton qui fait la même chose (je pense ?), sauf la syntaxe qui est différente, renverra aussi cette connexion non ?

    Dans tout les cas, je dois déclarer cette classe en début de page, et envoyer cette connexion en paramètre c'est ca ? L'avantage c'est juste d'avoir une seule connexion pour tous les objets de la page c'est ca ?

    Merci d'avance, je comprend de mieux en mieux

  10. #10
    Expert éminent
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Points : 7 762
    Points
    7 762
    Par défaut
    Un objet modèle qui construit lui même son propre driver de connexion est un défaut de conception assez inquiétant. Je te suggère de corriger ça soit avec un Singleton (si tu te fous pas mal du couplage que ça implique) invoqué directement par le modèle ou avec un une composition (comme je t'ai montré plus haut) l'instance pouvant venir d'un Singleton ou non.

  11. #11
    Membre expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Points : 3 947
    Points
    3 947
    Par défaut
    Sinon je vois pas trop la différence entre un singleton et une classe minimaliste
    C'est une d'optimisation, au final de rapidité.

    Une classe minimaliste (comme tu dis), il faudra créer une propriété pour lui attribuer cet Objet MySQLi (même chose si c'est uniquement une variable locale), ceci occupera de la mémoire car elle fera partie de la classe qui en fait l'instanciation.

    Avec un singleton où la méthode sera statique, on ne fera pas d'instanciation dans la classe, de même qu'on ne fera pas d'initialisation (ni dans une propriété ni dans une variable).
    On fait juste appel au singleton temporairement.

    Citation Envoyé par Benjamin Delespierre
    Un objet modèle qui construit lui même son propre driver de connexion est un défaut de conception assez inquiétant
    Tout le monde n'a pas besoin d'avoir un semi-remorque, une camionnette peu suffire.
    C'est plus léger, ça consomme moins, c'est moins cher, et c'est plus rapide.

    Je vois rien d'inquiétant à partir du moment où on a clairement défini dans son cahier des charges, son besoin (comme utiliser MySQLi uniquement, ou PDO + 1 driver d'office, uniquement).


    Personnellement, ça m'intéresse absolument pas d'intégrer un driver à mon singleton, et je ne vois pas qui va me dire que c'est un défaut de conception.
    Donc t’inquiètes pas

  12. #12
    Expert éminent
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Points : 7 762
    Points
    7 762
    Par défaut
    Citation Envoyé par RunCodePhp Voir le message
    C'est une d'optimisation, au final de rapidité.

    Une classe minimaliste (comme tu dis), il faudra créer une propriété pour lui attribuer cet Objet MySQLi (même chose si c'est uniquement une variable locale), ceci occupera de la mémoire car elle fera partie de la classe qui en fait l'instanciation.
    Non, en PHP les objets sont systématiquement passés par référence aux fonctions / méthodes, il n'y a donc pas de consommation mémoire supplémentaire ni de copie.

    Il vaut mieux avoir les deux: un singleton pour s'assurer que l'objet de connexion est unique (ou un pool de connexions équipé d'une fabrique pour ceux qui utilisent plusieurs SGBD différents) et une référence dans les objets modèle vers l'objet de connexion qu'ils doivent utiliser.
    On peut également, pour des raisons pratiques, équiper le singleton d'une fabrique d'objets modèles qui passerait lui même sa propre instance au constructeur.
    L'intérêt de coupler faiblement vos interfaces est de les rendre plus flexibles et donc plus évolutives Croyez-moi, cet investissement n'est jamais perdu.

    Un objet modèle qui construit lui même son propre driver de connexion est un défaut de conception assez inquiétant
    Tout le monde n'a pas besoin d'avoir un semi-remorque, une camionnette peu suffire.
    Tu mets les roues sur le toit de ta camionnette ? Pour rappel, la couche de connexion (ou le DBAL) doit se trouver en dessous de la couche DAO (les objets modèles à proprement parler). Sinon qu'est ce que ça veut dire ? que chaque instance de modèle porte une instance de connexion différente ? on voit aisément les problèmes que ça soulève.

  13. #13
    Membre expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Points : 3 947
    Points
    3 947
    Par défaut
    Non, en PHP les objets sont systématiquement passés par référence aux fonctions / méthodes, il n'y a donc pas de consommation mémoire supplémentaire ni de copie.
    Rien ne dit qu'il optera par un passage en paramètre comme tu l'a proposer.


    D'ailleurs, si on utilise un singleton, c'est limite absurde de le faire passer en paramètre dans le constructeur, autant faire référence au singleton directement là où on en a besoin.
    Nulle besoin aussi d'initialiser quoi que ce soit.
    Comme l'exemple que j'avais mis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $reussi = SQLI::Instance()->query($AddCovoiturage);
    (Je sens que ça ne va plaire).


    D'ailleurs, si on opte pour un passage en paramètre dans le constructeur le singleton, puis par la suite on le stock dans une propriété de la classe (comme $this->connexion), est-ce que cette propriété n'occuperait pas de l'espace mémoire ?
    Il me semble que c'est le cas, non ?


    Tu mets les roues sur le toit de ta camionnette ?
    Non, car ma camionnette n'a pas besoin de roues, elle vole

    Il n'y a pas grand monde qui comprend ce que tu racontes, le fond du problème est surtout là.
    Bob633 commence à peine à faire de la POO, et voilà que tu lui dis qu'il faut créer son projet de la même manière que la fusée Ariane.
    J'y vois là de la démesure, une disproportion dans la manière d'aborder les choses, c'est tout.
    Que dire alors de tous ces nombreux codeurs qui exploitent encore les fonctions mysql_* ?

  14. #14
    Expert éminent
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Points : 7 762
    Points
    7 762
    Par défaut
    D'ailleurs, si on utilise un singleton, c'est limite absurde de le faire passer en paramètre dans le constructeur, autant faire référence au singleton directement là où on en a besoin.
    Nulle besoin aussi d'initialiser quoi que ce soit.
    Comme je l'ai mentionné plus haut c'est un problème d'architecture lié au couplage. Utiliser le singelton directement dans la classe modèle va introduire un couplage fort et surtout masqué ! Si le prototype de la classe de singleton change, il faudra alors changer toutes les classes modèles, ce n'est pas le cas avec une composition (tant qu'on ne change pas non plus d'interface bien sûr).

    D'ailleurs, si on opte pour un passage en paramètre dans le constructeur le singleton, puis par la suite on le stock dans une propriété de la classe (comme $this->connexion), est-ce que cette propriété n'occuperait pas de l'espace mémoire ?
    Non, ça occupera une référence, donc c'est négligeable. De plus, faire porter l'objet de connexion à l'intérieur du modèle réduira le nombre d'appels à la méthode d'instance du singleton et de fait réduira le temps d'éxécution (les appels successifs de fonctions finissent par impacter les performances, on le remarque lors du profilling).

    Il n'y a pas grand monde qui comprend ce que tu racontes, le fond du problème est surtout là.
    Bob633 commence à peine à faire de la POO, et voilà que tu lui dis qu'il faut créer son projet de la même manière que la fusée Ariane.
    C'est ça le drame, pourtant j'utilise des mots clairs, je bégaie pas, j'ai pas l'accent... C'est bien qu'il prenne tout de suite les bonne habitudes, le couplage faible fait partie des bonnes pratiques de la programmation orienté objet.

    Que dire alors de tous ces nombreux codeurs qui exploitent encore les fonctions mysql_* ?
    Ce serait que de moi, ils seraient bannis à vue

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

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

    Informations forums :
    Inscription : Août 2003
    Messages : 6 692
    Points : 20 243
    Points
    20 243
    Par défaut
    Il n'y a pas grand monde qui comprend ce que tu racontes, le fond du problème est surtout là.
    Bob633 commence à peine à faire de la POO, et voilà que tu lui dis qu'il faut créer son projet de la même manière que la fusée Ariane.
    J'y vois là de la démesure, une disproportion dans la manière d'aborder les choses, c'est tout.
    pour le coup je me range du coté du méchant modérateur
    Quitte à faire de la POO autant la faire correctement dès le départ. perso on m'avais jamais expliqué les problématiques de couple fort entre les classes ... le jour ou ça à posé problème j'ai compris ma douleur et maintenant j'y fait attention.

    Après peut être que Benjamin utilise des termes un peu technique pour un débutant qui demanderais sans doute à être développé mais là c'est pas son job. Il propose la bonne solution technique à l'intéressé de s'instruire

    Pour la culture : [ame="http://www.google.fr/search?sourceid=chrome&ie=UTF-8&q=php+injection+d%C3%A9pendance"]Injection de dépendance[/ame]

  16. #16
    Membre expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Points : 3 947
    Points
    3 947
    Par défaut
    Citation Envoyé par Benjamin Delespierre
    Si le prototype de la classe de singleton change, il faudra alors changer toutes les classes modèles, ce n'est pas le cas avec une composition (tant qu'on ne change pas non plus d'interface bien sûr).
    Justement.
    Si dans son cahier des charges il est dit que le prototype ne changera pas, je ne vois pas de raison d'intégrer une fonctionnalité qui ne sera jamais exploiter.
    C'est inconcevable ça ?


    C'est ça le drame, pourtant j'utilise des mots clairs, je bégaie pas, j'ai pas l'accent...
    Ce n'est pas un problème de diction, juste ne pas parvenir à ce mettre au même niveau.
    Tu ne te rends pas compte du grand écart que cela provoque.
    Mais il ne faut surtout pas mal le prendre.


    Moi même j'ai dû mal à adhérer qu'on se doit d'intégrer à son model n driver au niveau de sa connexion.
    Je ne vois pas cela comme un "devoir", mais plutôt comme quelque chose d'optionnel.
    - Soit le projet en a besoin : On l'intègre
    - Soit le projet en a pas besoin : On ne l'intègre pas.
    Peu importe si cela apporte une performance supplémentaire, car il y aura une sur-couche de codes supplémentaires pour le gérer.
    Il faut déjà du temps pour le faire, et du temps pour le maintenir (mise à part la compréhension).

  17. #17
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 051
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 051
    Points : 1 638
    Points
    1 638
    Par défaut
    Hum je viens de lire la conversation.

    En effet j'ai du mal avec tous les termes évoqués. Je code très peu en PHP, juste pour des petits sites persos.

    Du coup, vu que ca fonctionne en l'état actuel, je vois pas énormément ce que j'y gagnerais à faire cela.

    Je veux dire, mon site n'aura pas 1.000.000 de visiteurs par jour, et encore moins 10.000.000 de requêtes à la seconde. Du coup, instancie ma connexion dans le constructeur, c'est pas si gênant que ca si ?

    Je regarderais quand même cette solution, car ca m'intéresser d'évoluer (tant qu'à faire ..) mais je voulais être sûre quand vous dites "mauvaise conception".

    Car c'était simple à mettre en place, pas de redondance mis apart le fait que si on utilise 2 objets, faut instancier 2 fois la connexions du coup (est-ce vraiment gênant ?). Je ne gère pas plus de 2 ou 3 objets par page.

    Enfin je réponds peut-être de façon simpliste, car je suis au boulot, mais je prendrais le temps de lire et relire vos réponses ce soir jusqu'à voir l'utilité de complexifier mon code pour améliorer le tout.

  18. #18
    Expert éminent
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Points : 7 762
    Points
    7 762
    Par défaut
    Du coup, instancie ma connexion dans le constructeur, c'est pas si gênant que ca si ?
    Conceptuellement c'est faire les choses à l'envers, c'est ce que j'ai voulu souligner tout au long du thread. Mais si ça te gêne pas, fais-le. Tu verra par toi même où ça mène.

    Car c'était simple à mettre en place, pas de redondance mis apart le fait que si on utilise 2 objets, faut instancier 2 fois la connexions du coup (est-ce vraiment gênant ?).
    C'est une tautologie qui revient à dire "si on oublie les redondances, il n'y a pas de redondance."

    Pour épiloguer sur ma diatribe ci-dessus, je dirait qu'il n'y a pas de vérité absolue en programmation, si ça marche et que ça te conviens, fais-le si ça réponds à ton besoin. La seule chose qu'il ne faut absolument jamais faire c'est tordre un besoin en raison de problèmes d'implémentation. J'ai juste voulu attirer ton attention sur les bonnes pratiques en vigueur dans le monde de l'OOP, libre à toi de les suivre ou pas.

    Si ça t'intéresse, voici, en version simplifiée les classes que j'utilise pour mes modèles:
    Code PHP : 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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    class Database {
     
    	protected static $_instance;
     
    	final protected function __construct () {
    		throw new RuntimeException("Illegal call of " . __METHOD__);
    	}
     
    	public static function instance () {
    		if (isset(self::$_instance))
    			return self::$_instance;
     
    		list($dsn, $username, $password, $options) = func_get_args() + array('', null, null, array());
    		return self::$_instance = new PDO($dsn, $username, $password, $options);
    	}
     
    	public static function factory ($model, $id = null) {
    		if (!class_exists($model, true))
    			throw new RuntimeException("Model calss not found: {$model}");
     
    		if (!in_array('Model', class_implements($model)))
    			throw new RuntimeException("{$model} class doesn't implements Model interface");
     
    		return new $model(self::$_instance, $id);
    	}
    }
     
    interface Model {
     
    	public function __construct (PDO $pdo, $id = null);
    	public function create (array $data);
    	public function retrieve ($id);
    	public function update (array $data = array());
    	public function delete ();
    }
     
    abstract class BaseModel implements Model {
     
    	protected $_pdo;
     
    	protected $_data;
     
    	public function __construct (PDO $pdo, $id = null) {
    		$this->_pdo = $pdo;
    		if ($id !== null && !$this->retrieve($id))
    			throw new RuntimeException('Cannot retrieve data');
    	}
     
    	public function getData () {
    		return $this->_data();
    	}
     
    	public function __get ($key) {
    		return $this->__isset($key) ? $this->_data[$key] : null;
    	}
     
    	public function __set ($key, $value) {
    		if ($this->__isset($key))
    			$this->_data[$key] = $value;
    		else
    			throw new RuntimeException("Cannot set {$key}: property doesn't exists");
    	}
     
    	public function __isset ($key) {
    		return isset($this->_data[$key]);
    	}
     
    	public function __unset ($key) {
    		unset($this->_data[$key]);
    	}
    }
     
    // Exemple de classe de modèle concrête
    class User extends BaseModel {
     
    	public function create (array $data) {
    		$query = "INSERT IGNORE INTO `mydb`.`users` SET `login`=:login,`password`=:password,`mail`=:mail";
    		$data  = filter_var_array($data, array(
    			'login'    => FILTER_SANITIZE_STRING,
    			'password' => FILTER_UNSAFE_RAW,
    			'mail'     => FILTER_SANITIZE_EMAIL
    		));
    		$stmt  = $this->_pdo->prepare($query);
    		if (!$stmt->execute($data)) {
    			return false;
    		}
     
    		$inerted_id = $this->_pdo->lastInsertId();
    		return $this->retrieve($inerted_id);
    	}
     
    	public function retrieve ($id) {
    		$query = "SELECT `id`,`login`,`password`,`mail` FROM `mydb`.`users` WHERE `id`=:id";
    		$stmt  = $this->_pdo->prepare($query);
     
    		if (!$stmt->execute(array('id' => $id))) {
    			return false;
    		}
    		$this->_data = $stmt->fetch(PDO::FETCH_ASSOC);
    		return $this;
    	}
     
    	public function update (array $data = array()) {
    		$query = "UPDATE `mydb`.`users` SET `login`=:login,`password`=:password,`mail`=:mail WHERE `id`=:id";
    		$data += $this->_data;
    		$data  = filter_var_array($data, array(
    			'id'       => FILTER_SANITIZE_NUMBER_INT,
    			'login'    => FILTER_SANITIZE_STRING,
    			'password' => FILTER_UNSAFE_RAW,
    			'mail'     => FILTER_SANITIZE_EMAIL
    		));
    		$stmt  = $this->_pdo->prepare($query);
    		if (!$stmt->execute($data)) {
    			return false;
    		}
     
    		$this->_data = $data;
    		return $this;
    	}
     
    	public function delete () {
    		$query = "DELETE FROM `mydb`.`users` WHERE `id`=:id";
    		$stmt  = $this->_pdo->prepare($query);
    		$data  = filter_var_array($this->_data, array(
    			'id'       => FILTER_SANITIZE_NUMBER_INT,
    		));
    		return $stmt->execute($data);
    	}
    }

    On y retrouve les patterns: composition, singleton et factory. Libre à vous de vous en servir ou de vous en inspirer.

    Demonstration
    Code PHP : 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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    Database::instance('mysql:dbname=mydb;host=127.0.0.1', '***', '***');
     
    create_db_struct();
     
    echo "Creation:";
    $user = Database::factory('User');
    $user->create(array(
    	'login' => 'foo',
    	'password' => md5('bar'),
    	'mail' => 'foo@bar.com'
    ));
    display_table_content('mydb.users');
     
    echo "Update:";
    $user->login = 'another login';
    $user->update();
    display_table_content('mydb.users');
     
    echo "Delete:";
    $user->delete();
    display_table_content('mydb.users');
     
     
    // for debug //
    function display_table_content ($tbl) {
    var_dump( Database::instance()->query("SELECT * FROM $tbl")->fetchAll(PDO::FETCH_ASSOC) );
    }
     
    function create_db_struct () {
    $sql = <<< EOSQL
    CREATE TABLE IF NOT EXISTS mydb.users (
      id INT NOT NULL AUTO_INCREMENT,
      login VARCHAR(45) NOT NULL,
      password VARCHAR(45) NOT NULL,
      mail VARCHAR(90) NOT NULL,
      PRIMARY KEY (id)
    ) ENGINE=InnoDB;
    EOSQL;
    Database::instance()->query($sql);
    Database::instance()->query('TRUNCATE mydb.users');
    }

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

Discussions similaires

  1. Classe javascript, variable indéfinie.
    Par marwen1987 dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 28/04/2009, 20h02
  2. Variable de classe JPanel
    Par Janitrix dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 11/12/2005, 17h50
  3. débutant:utilisation de variable entre classe
    Par troojan dans le forum MFC
    Réponses: 1
    Dernier message: 07/12/2005, 23h31
  4. XMLC_SkinPath : variable indéfinie
    Par johan_barbier dans le forum XMLRAD
    Réponses: 5
    Dernier message: 11/10/2005, 11h04
  5. Réponses: 6
    Dernier message: 23/09/2005, 12h54

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