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 :

Queqlues questions sur un code de models (interractions avec la bd en POO)


Sujet :

Langage PHP

  1. #1
    Membre éprouvé
    Avatar de beegees
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2004
    Messages
    3 610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 3 610
    Points : 1 277
    Points
    1 277
    Par défaut Queqlues questions sur un code de models (interractions avec la bd en POO)
    Bonjour à tous,

    Je débute en POO (avec PHP).

    Pour débuter, j'ai décidé de m'attaquer au models et donc à l'interraction avec la base de données.

    J'ai lu beaucoup de tuto, j'ai regardé beaucoup de vidéo, et j'en suis arrivé à ce résultat (pour l'insertion ou la mise à jour d'une donnée dans ma bd) :

    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
    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
    class Model{
     
    	public $dbh;
    	public $table;
    	public $id;
     
    	public function Model(){
    		try{
    			$this->dbh = new PDO("mysql:host=localhost;dbname=domabdd","root","mdp");
    			$this->dbh->exec('SET NAMES utf8');
    		}
    		catch(Exception $e)
    		{
    			die(print_r("Erreur : ".$e->getMessage()));
    		}
    	}
     
    	/**
    	 * Lit une ligne dans la base de donnée par rapport à l'ID de l'objet
    	 * @param $fields Liste des champs à récupérer
    	 * 
    	 **/
    	public function read($fields=null)
            {
    		if($fields==null){            $fields = "*";        }
    		$sql = "SELECT $fields FROM ".$this->table." WHERE id=".$this->id;
    		$req = $this->dbh->prepare($sql);
    		$req->execute();
    		return $req->fetchAll();
    	}
     
    	/**
    	 * Sauvegarde les donnée passé en paramètre dans la base de donnée
    	 * @param $data Donnée à sauvegarder
    	 * */
    	public function save($data, $marqueurs = array()){
    		if(isset($data["id"]) && !empty($data["id"])){
    			$sql = "UPDATE ".$this->table." SET ";
    			foreach($data as $k=>$v){
    				if($k!="id"){
    					$sql .= "$k=$v,";
    				}
    			}
    			$sql = substr($sql,0,-1);
    			$sql .= "WHERE id=".$data["id"];
    		}
    		else{
    			$sql = "INSERT INTO ".$this->table."(";
    			//unset($data["id"]);
    			foreach($data as $k=>$v){
    				$sql .= "$k,";
    			}
    			$sql = substr($sql,0,-1);
    			$sql .=") VALUES (";
    			foreach($data as $v){
    				$sql .= "$v,";
    			}
    			$sql = substr($sql,0,-1);
    			$sql .= ")";
    		}
                    //echo "ici ". $sql;
     
    		$req = $this->dbh->prepare($sql);
                    foreach($marqueurs as $key => $info)
                    {
                            //key est l'index (1,2...) qui doit commencer à 1 !
                            $req->bindParam($key+1, $info["key"], $info["type"]);
                            //echo $info["key"];
                            //echo $info["type"];
     
                    }
    		if(!isset($data["id"])){
    			//$this->id=PDO::lastInsertId;
    		}
    		else{
    			$this->id = $data["id"];
    		}
     
                    $req->execute();
    	}
    Je pense que ce code est correct et qu'il va me permettre de devoir écrire moins de code.

    Par contre, je me pose certaines questions par rapport à ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    $insererPersoC = new Model();
    $insererPersoC->table = "personne_de_contact";
    		$insererPersoC->save(array('ref_Nom'=>'?','ref_Prenom'=>'?','ref_Email'=>'?','ref_Tel'=>'?','ref_GSM'=>'?','ref_FAX'=>'?'),$datas);
    Pour utiliser l'objet "Model" et pour utiliser la méthode add, je dois écrire le code ci-dessus.

    Je dois aussi écrire le code qui va créer le tableau "info" qui est passé à la méthode 'add' :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $donnees = new ParametersInfos();
    $datas = $donnees->add(array($ref_Nom_i => 's',
    // si je mets ceci =>'s' ça veut dire que je passe PDO::PARAM_STR (donc 2)
    //cela me permet de moins écrire de code
    //pour un entier, il faudra mettre ceci $_POST['ns']=>PDO::PARAM_INT
    				$ref_Prenom_i => 's',
    				$ref_Email_i => 's',
    				$ref_Tel_i => 's',
    				$ref_GSM_i => 's',
    				$ref_FAX_i =>'s'
    		     ));
    avec cette classe :

    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
    25
    26
    27
    28
     
    <?php
     
        class ParametersInfos
        {
     
            function add($parametres)
            {
                $info = array();
                foreach($parametres as $key=>$value)
                {
                    //dans la majorité des cas, la key sera "PDO::PARAM_STR" donc 2, si je n'indique pas le type, il prendra 2 par défaut
                    switch($value)
                    {
                        case "s" : $value = PDO::PARAM_STR;
                        break;
                        case "i": $value = PDO::PARAM_INT;
                        break;   
                    }
                    $info[] = array('key'=>$key,'type'=>$value);
                }
     
                return $info;
            }
        }
     
     
    ?>
    Je trouve que ça fait beaucoup de code et peu d'avantage par rapport à ce que je faisais avant (procédural) ?

    1) Pensez-vous que ce code peut être amélioré (afin d'écrire moins de code lors de l'utilisation de l'objet) ?
    2) pensez-vous que tout cela est bien protégé contre les injuctions ?
    3) Je n'utilise pas de constructeur, d'atributs, d'interface... dans ce code, pensez-vous que cela pourrait améliorer ce code ?

    Merci d'avance.

    bee

  2. #2
    Membre régulier Avatar de moogli
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 58
    Points : 102
    Points
    102
    Par défaut
    salut,

    pour respecter les habitudes du modèles objet tu devrais passer les propriétés en privée et ajouter des "setter / getter" dessus (cela peux aussi te permettre de contrôler les données fournit).

    Le problème de ce que tu propose est que ce n'est pas assez générique.
    Tu impose que les clefs primaires soient nommées "id" et ce n'est pas toujours le cas

    Tu ne permet pas de faire un select sur toute une table ou avec jointure.

    As tu essayé de simplement utiliser PDO avant de la surcharger ?

    personne je partirais sur une interface model, et une classe dao par table ou plutot par entité de ton modèle qui implémente l'interface plus une factory qui pourras instancier le bon objet DAO.
    Tu peux passer en paramètre du constructeur des DAO une instance de PDO afin d'éviter de devoir fournir les identifiant à toute les classes (perso j'utilise une classe avec une méthode statique qui permet de gérer une instance de PDO, style singleton).

    Il te faudra des objets qui représentent les entités (style pojo java) et tu passe en paramètre des méthodes un "pojo". Cette méthode s'occupe de créer la requete et de l'executer.

    ainsi une validation de formulaire peux résumer a
    - instanciation de la factory
    - création d'un pojo avec les info du formulaire
    - instanciation de l'objet DAO souhaité
    - $dao->save($pojo);

    Tu va avoir, au total, plus de code, plus de classe, mais coté simplicité et lisibilité du code tu doit t'y retrouver

    Après suivant tes besoin tu n'a peut être pas besoin de re coder un ORM ?

    @+

  3. #3
    Membre éprouvé
    Avatar de beegees
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2004
    Messages
    3 610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 3 610
    Points : 1 277
    Points
    1 277
    Par défaut
    Salut,

    Un grand merci pour ta réponse.



    Citation Envoyé par moogli Voir le message
    salut,

    pour respecter les habitudes du modèles objet tu devrais passer les propriétés en privée et ajouter des "setter / getter" dessus (cela peux aussi te permettre de contrôler les données fournit).
    Tu as raison, je vais m'en charger.

    Le problème de ce que tu propose est que ce n'est pas assez générique.
    Tu impose que les clefs primaires soient nommées "id" et ce n'est pas toujours le cas
    Je recherche justement une solution générique (j'ai du renommer mes clés primaires en id, ce qui n'était pas le cas dans mes tables).


    Tu ne permet pas de faire un select sur toute une table ou avec jointure.
    Je ne pense pas avoir montré tout mon code, cette méthode permet de sélectionner une ligne d'une table bien précise :

    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
     
    public function find($data=array()){
    		$conditions = "1=1";
    		$fields = "*";
    		$limit = "";
    		$order = "id DESC";
    		extract($data);
    		if(isset($data["limit"])){ $limit = "LIMIT ".$data["limit"]; }
    		$sql = "SELECT $fields FROM ".$this->table." WHERE $conditions ORDER BY $order $limit";
    		$req = $this->dbh->prepare($sql);
    		$req->execute();
    		$d = array();
    		while($data = $req->fetch(PDO::FETCH_ASSOC)){
    			$d[] = $data;
    		}
    		return $d;
    	}
    As tu essayé de simplement utiliser PDO avant de la surcharger ?
    Je ne comprends pas cette question. J'ai surchargé une de mes méthodes ?


    personne je partirais sur une interface model, et une classe dao par table ou plutot par entité de ton modèle qui implémente l'interface plus une factory qui pourras instancier le bon objet DAO.
    Waow, beaucoup de nouveaux termes là. DAO (Direct Access object ?, si oui, j'utilisais cela en VBA avec ACCESS). Aurais-tu un exemple de code stp (je vais googler entre temps)

    Tu peux passer en paramètre du constructeur des DAO une instance de PDO afin d'éviter de devoir fournir les identifiant à toute les classes (perso j'utilise une classe avec une méthode statique qui permet de gérer une instance de PDO, style singleton).
    Aurais-tu un exemple de code stp

    Tu va avoir, au total, plus de code, plus de classe, mais coté simplicité et lisibilité du code tu doit t'y retrouver
    Ce qui m'intéresse, c'est de devoir moins écrire de code en dehors des classes, tu crois que ça sera le cas ?

    Après suivant tes besoin tu n'a peut être pas besoin de re coder un ORM ?
    Non, je ne pense pas en effet.

    Merci encore pour l'aide.

    bee

  4. #4
    Membre régulier Avatar de moogli
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 58
    Points : 102
    Points
    102
    Par défaut
    Ce qui m'intéresse, c'est de devoir moins écrire de code en dehors des classes, tu crois que ça sera le cas ?
    Oui oui c'est réalisable

    Je ne comprends pas cette question. J'ai surchargé une de mes méthodes ?
    Je me suis mal exprimé, je me demandais simplement si le fait d'utiliser PDO n'était pas suffisant

    Le problème de ce type d'objet c'est qui faut définir la structure de la base quelque part (à moins qu'il cherche lui même les infos mais la pour le coup soit il le fait une fois et il y aura des fichier de paramètre soit il le fait a chaque fois et c'est anti-performant

    Donc pour pour faire "simple" il peut être préférable d'avoir des pojo qui représentent les entités ("tables") de la base (version java ^^).
    et des classe qui s'occupe de l'accès aux données, le tout basé sur une interface pour pouvoir l'utiliser via une classe "usine" qui créra les objet à la volé sans que tu te prenne la tête à l'utilisation, parce qu'avant ça peux l'être.
    Le tout va tendre vers un MCV

    pour faire simple un exemple rapide
    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
    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
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    <?php
    /**
     * Interface des objet DAO (acces au sgbd) 
     *
     */
    interface InterfaceDao {
    	public function __construct(\PDO $pdo);
    	/**
    	 * Permet l'ajout d'une entrée dans la table souhaité
    	 * 
    	 * @param unknown_type $pojo        	
    	 */
    	public function add($pojo);
    	/**
    	 * permet de récupérer un élément précis, on peu imaginer que le paramètre
    	 * soit nullable et dans ce cas retourner tout les éléments
    	 * 
    	 * @param unknown_type $id        	
    	 */
    	public function get($id);
    	/**
    	 *
    	 *
    	 * Mise à jour d'un élément précis
    	 * 
    	 * @param unknown_type $pojo        	
    	 */
    	public function update($pojo);
    	/**
    	 * suppression d'un élément
    	 * 
    	 * @param unknown_type $pojo        	
    	 */
    	public function delete($pojo);
    }
     
    /**
     * Pjo Utilisateur
     *
     */
    class User {
    	private $idUser;
    	private $nom;
    	private $prenom;
    	private $email;
    	private $psswd;
     
    	// pour le cas ou, attention si tu prévois d'utiliser le constructeur
    	// pour instancier la classe complète prévoir d'avoir des paramètre
    	// facultatif
    	public function __construct() {
    	}
    	/**
    	 *
    	 * @return the $nom
    	 */
    	public function getNom() {
    		return $this->nom;
    	}
     
    	/**
    	 *
    	 * @return the $prenom
    	 */
    	public function getPrenom() {
    		return $this->prenom;
    	}
     
    	/**
    	 *
    	 * @return the $email
    	 */
    	public function getEmail() {
    		return $this->email;
    	}
     
    	/**
    	 *
    	 * @return the $psswd
    	 */
    	public function getPsswd() {
    		return $this->psswd;
    	}
     
    	/**
    	 *
    	 * @param field_type $nom        	
    	 */
    	public function setNom($nom) {
    		$this->nom = $nom;
    	}
     
    	/**
    	 *
    	 * @param field_type $prenom        	
    	 */
    	public function setPrenom($prenom) {
    		$this->prenom = $prenom;
    	}
     
    	/**
    	 *
    	 * @param field_type $email        	
    	 */
    	public function setEmail($email) {
    		$this->email = $email;
    	}
     
    	/**
    	 *
    	 * @param field_type $psswd        	
    	 */
    	public function setPsswd($psswd) {
    		$this->psswd = $psswd;
    	}
    	/**
    	 *
    	 * @return the $idUser
    	 */
    	public function getIdUser() {
    		return $this->idUser;
    	}
     
    	/**
    	 *
    	 * @param field_type $idUser        	
    	 */
    	public function setIdUser($idUser) {
    		$this->idUser = $idUser;
    	}
    }
    /**
     * La classe DAO utilisateur
     *
     */
    class UserDao implements InterfaceDao {
    	private $dao;
    	public function __construct(\PDO $pdo) {
    		if ($pdo !== null)
    			$this->pdo = $pdo;
    		else
    			throw new InvalidArgumentException ( 'Objet PDO obligatoire' );
    	}
    	/*
    	 * (non-PHPdoc) @see InterfaceDao::add()
    	 */
    	public function add(User $pojo) {
    		if (empty ( $pojo ))
    			throw new InvalidArgumentException ( 'Objet null ...' );
    		$sql = 'insert into user (\'nom\',\'prenom\',\'email\',\'passwd\') values('
    				 . $this->pdo->quote ( $pojo->getNom() ) . ','
    				 . $this->pdo->quote ( $pojo->getPrenom () ) . ','
    				 . $this->pdo->quote ( $pojo->getEmail () ) . ','
    				 . $this->pdo->quote ( $pojo->getPasswd () ) . ')';
    		$this->pdo->query ( $sql );
     
    		// je te laisse faire les vérifications de bon déroulement :)
    	}
     
    	/*
    	 * (non-PHPdoc) @see InterfaceDao::delete()
    	 */
    	public function delete($pojo) {
    		if (empty ( $pojo ))
    			throw new InvalidArgumentException ( 'Objet null ...' );
    		if (! empty ( $pojo->getIduser () ))
    			$sql = 'delete from user where iduser=' . $this->pdo->quote ( $pojo->getIduser (), PDO::PARAM_INT );
    		$this->pdo->exec ( $sql );
    		// idem :)
    	}
    	// le reste à ton imagination
    	/*
    	 * (non-PHPdoc) @see InterfaceDao::get()
    	 */
    	public function get($id) {
    		if (empty ( $id ))
    			throw new InvalidArgumentException ( 'Objet null ...' );
    	}
     
    	/*
    	 * (non-PHPdoc) @see InterfaceDao::update()
    	 */
    	public function update($pojo) {
    		if (empty ( $pojo ))
    			throw new InvalidArgumentException ( 'Objet null ...' );
    	}
    }
    /**
     * un exemple de controleur trop basique ;)
     *
     */
    class Controleur {
    	private $pdo;
    	public function __construct() {
    		// instanciation de l'ibjet PDO que l'on stock dans $this->pdo
    	}
    	public function addUser($data) {
    		// tu vérifie que tout les champs obligatoire sont bon, et bien formater
    		// (que l'email soit correct etc)
    		$user = new User ();
    		$user->setEmail ( $data ['email'] );
    		$user->setNom ( $data ['nom'] );
    		$user->setPrenom ( $data ['prenom'] );
    		// bon y aura surement un encodage / encryptage / hash qui va trainer :)
    		$user->setPsswd ( $data ['passwd'] );
    		$userDao = new UserDao ( $this->pdo );
    		$userDao->add ( $user );
    	}
    }
     
    // utilisation
    if (! empty ( $_POST )) {
    	$c = new Controleur ();
    	$c->addUser ( $_POST );
    }
    Maintenant imagine que le contrôleur n'ai pas une méthode par action mais une méthode générique qui va instancier à la volée la classe DAO dont il aura besoin pour valider le formulaire qui lui est soumis (par exemple via un champs caché, le nom du bouton input etc etc), il peux faire quelque chose comme ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?php
    // validation
    if (!empty($_POST)){
        $ctrl = new Controleur();
        $ctrl->validForm($_POST);
    }
    // et la méthode validForm (par exemple)
    function validForm($post) {
        $class = $valeurDuChamp.'Dao';
        $dao = new $class();
        $dao->add($post);
    }
    ?>
    Là tu à séparé la base de donnée du reste, reste à séparée l'affichage de la couche métier et tu es en bonne voie pour un MVC

    Ce n'est pas forcément super clair n'hésite pas


    @+

Discussions similaires

  1. Questions sur le code
    Par Pedro dans le forum Sepi
    Réponses: 5
    Dernier message: 23/12/2006, 13h10
  2. une question sur le code ASP-Nuke
    Par ghita269 dans le forum ASP
    Réponses: 1
    Dernier message: 14/01/2006, 09h41
  3. [Conception] Question sur un code permettant de connaître le nombre de connectés
    Par inferno66667 dans le forum PHP & Base de données
    Réponses: 11
    Dernier message: 19/12/2005, 19h49
  4. Question sur le code compactage de la FAQ
    Par Nicko29 dans le forum Access
    Réponses: 7
    Dernier message: 14/11/2005, 20h19

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