[Débutant] Faut'il séparer le code des données ?

Eléphant du PHP | 189 Messages

30 juil. 2009, 14:14

Bonjour à tous,

Alors une question qui vous paraitra certainement toute simple, mais qui me tracasse pas mal.

Je tente de créer mes différentes class.
On m'a conseillé de séparer les données de ma class, et donc de fournir ces données à mon constructeur.

Imaginons une class utilisateur :
$user = new Utilisateur("Moi","24 ans","Belgique");
Pensez-vous qu'il vaut mieux faire comme précédement, ou alors :
$user = new Utilisateur($id);
Est aussi bon ?

Sachant que dans mon constructeur du coup, j'aurais une requete sql...

Mon soucis, est que je n'arrive pas à distinguer jusqu'où doit aller cette séparation.

Dois-je filer l'ensemble des données au constructeur (et ou via des set) ou peut on imaginer qu'une class se remplisse d'elle même ?

Merci à vous et bonne journée

Eléphant du PHP | 111 Messages

30 juil. 2009, 15:20

$user = new Utilisateur("Moi","24 ans","Belgique");
Okay, ça ça ne va pas du tout, parce que tu vas pas faire cette opération pour chaque utilisateur de ta base :s

Par contre, l'astuce :
$utilisateur = new Utilisateur($id);
Ou
$utilisateur = new Utilisateur($array);
En fonction de ce qui est passé, il faut une requête ou pas.

Eléphant du PHP | 189 Messages

30 juil. 2009, 15:37

Merci pour ta réponse,
$user = new Utilisateur("Moi","24 ans","Belgique");
Okay, ça ça ne va pas du tout, parce que tu vas pas faire cette opération pour chaque utilisateur de ta base :s
Oui,Oui je sais, plutôt que ça je passerais un tableau..

$utilisateur = new Utilisateur($id);
Ou
$utilisateur = new Utilisateur($array);
En fonction de ce qui est passé, il faut une requête ou pas.
Mais justement, ne vaut il pas mieux faire ma requête dans ma page index.php, et envoyer les données à ma class.. ne serait-ce que pour pouvoir la réutiliser sans connaître la structure de la base de donnée ?

Je précise que ce n'est pas mon idée, je veux vraiment savoir ce qui est préconisé dans ce cas la ?

Eléphant du PHP | 111 Messages

30 juil. 2009, 16:52

Ta classe Utilisateur :
Utilisateur {

private $id;
private $nom;
private $prenom;

// renvoie un utilisateur depuis une requête
public function getUserFromId( $id ) {
$query = "select ...";
}
// renvoie une utilisateur depuis un tableau 
public function getUserFromArray($array) {
$this->id = $array[0];
$this->nom = ...
}

public function del($id {

}
}
Là, c'est un fonctionnement métier. Les deux méthodes getUser retournent des données formattées de la meme manière.

Si tu envoies tes données depuis ton fichier index, cela signifie que ta classe s'adapte aux données envoyées (donc pas forcément un user ?), et là ça va être lourd à gérer :s

Dans un modèle de type ORM (objet relationnal mapping), on s'y prend à peu près comme dans la classe que je t'ai montrée.

Eléphant du PHP | 245 Messages

30 juil. 2009, 18:00

IL y a plusieurs méthode pour construire une classe dont une peut être à peu près celle là :

class Utilisateur
{
   function __construct($id_utilisateur)
  {
      $requete="select * from utilisateurs where id_utilisateur=$id_utilisateur";
      $result=mysql_query($requete);
     if($recap=mysql_fetch_assoc($result))
    {
         foreach($recap as $cle =>$valeur)
        {
            $this->$id=$valeur;
         }
    }
    mysql_free_result($result);

  }
}

ViPHP
ViPHP | 928 Messages

30 juil. 2009, 18:57

Idéalement si tu veux renseigner des informations dans ta classe il faut utiliser les getter / setter :
$utilisateur = new Utilisateur();
$utilisateur->setName('Moi');
$utilisateur->setAge('24 ans');
$utilisateur->setCountry('Belgique');
Après c'est sur que si tu dois entrer 50 informations c'est pas mal redondant ...

Petit nouveau ! | 8 Messages

31 juil. 2009, 08:07

salut,

Comme te l'a signalé narcisse, il existe une technique qui permet de séparer définitivement la partie données et les objets : l'Object Relationnal Mapping.
Parmis les plus connus, on trouve : Doctrine, PHPMyObject, ... Voila un petit comparatif que tu peux consulter : http://www.phpindex.com/index.php/2009/ ... m-pour-php.

La mise en place d'un ORM peut être assez lourde donc à voir si cela vaut le coup. Tout dépend de l'envergure de ton application, pour un gros project cela peut être intéréssant.

Pour de plus petit projets, je pense qu'il sera plus facile de maintenir un code où les données sont récupérées depuis le constructeur de la classe, pour les raisons suivantes :

- si tu utilises des instances de la classe User sur d'autres pages que la page index, tu vas devoir refaire le même traitement à chaque fois.

- si la structure de ta base de données est ammenée à changer, tu vas devoir modifier toutes les pages où tu instancies des objets User

- si la classe ne récupère pas elle-même les données depuis la base, cela accroît les risques d'erreurs : le développeur doit penser ( et sans se tromper ) à initialiser manuellement tous les attributs de la classe User pour chaque instance créée ( un peu rébarbatif )

- tu limites les risques de viscosité au sein de l'application, cad que chaque développeur peut définir les propriétés des instances de User à sa sauce. Si la structure de ta classe doit être modifiée un jour, cela va être galère pour tout vérifier.

Personnellement, je pense que sécurité et l'évolutivité doivent toujours primer sur la facilité.

++

Eléphant du PHP | 189 Messages

02 août 2009, 13:48

Merci beaucoup foxdie pour cette réponse très complète..

Mon application est loin d'être un projet très lourd, je pense donc que je vais pas séparer les données du traitements.. Ça me facilitera les choses..

Encore merci pour cette réponse !

Eléphant du PHP | 199 Messages

02 août 2009, 15:30

Je viens de voir ce qu'il y a été écrit.
Cependant quand on fait:

$test=new Users($id); 
On met quoi dans le constructeur quand dans la classe on a plusieurs attributs comme:
le nom
l'age
le prenom
....

Même question pour l'array.[/color]

Petit nouveau ! | 8 Messages

03 août 2009, 13:51

par exemple :
function __construct( $iduser ){

     //récupérer les données depuis la base

     $query = "SELECT * FROM `users` WHERE iduser = '" . intval( $iduser ) . "' LIMIT 1";
     $result = @mysql_query( $query, ... );

     //gestion des erreurs

     if( !mysql_num_rows( $result ) ){ //l'utilisateur n'existe pas

         trigger_error( "Impossible...blablabla...", E_USER_ERROR );
         exit();

     }

     //initisaliser les données membres

     $this->login = mysql_result( $result, 0, "login" );
     $this->email = mysql_result( $result, 0, "email" );
     $this->nombrededentsdesagesse = mysql_result( $result, 0, "nombrededentsdesagesse" ); //^^
     //etc, ...

}

Eléphant du PHP | 189 Messages

04 août 2009, 08:08

Dernière question, après je pourrais mettre ce sujet en résolu..

Comment verriez-vous la chose , j'ai une classe de connexion MySql, et dans ma class User je devrais faire quelques requêtes..
Dois-je passer l'identifiant de ma classe au constructeur ?
Utiliser une variable global pour l'instance de ma classe Mysql ?

Merci à vous et bonne journée


Edit :
- Et comment enregistrer ce genre de donnée :
Serveur
|--> Status Ok
|--> Date : Now
|--> Groupe : Groupe1
|--> Nextcheck : Dans 10min
|--> Maintenance
|------> Demain 18h
|------> Après demain 14h
....

Dois-je créer un tableau de classe Item, ou je mettrais toutes ces donnes et des accesseurs ?
Un tableau a 3 dimensions ?

Et du coup, vu la quantité de donnée extraite :

Je dois sur une des pages récupérer tout les status d'un groupe dois-je tout calculer et mètre mes item dans une class ou dans mon tableau à 3 dimensions
Et d'accéder qu'au donnée recherchée avec un accesseur spécifique?

Ou je ne calcule que le minimum en faisant une deuxième requêtes si nécessaire ?

Eléphanteau du PHP | 19 Messages

04 août 2009, 19:45

On instancie pas un objet utilisateur si on ne l'a pas vérifié ! Où alors c'est déjà fait et tu as mis la charue avant les boeufs ...
$membre = new user();
$userID = $membre->check($post['login'], $post['password']);
if( $userID>0 )
{
$membre->login(...);
}else{
$membre->create(...);
}
ou quelquechose du genre.
Celui qui recherche la vengeance devrait commencer par creuser 2 tomnes (Confucius)

Eléphant du PHP | 189 Messages

05 août 2009, 08:07

Ca dépend du point de vue..

Pour moi, un utilisateur non connecté est quand même un utilisateur avec un profil "Invité" et donc j'instancie toujours ma class, avec plus ou moins de donnée..

Par contre je n'ai toujours pas d'idée pour les autres questions, je vais ré ouvrir un topic..

Petit nouveau ! | 8 Messages

08 août 2009, 10:31

Dernière question, après je pourrais mettre ce sujet en résolu..

Comment verriez-vous la chose , j'ai une classe de connexion MySql, et dans ma class User je devrais faire quelques requêtes..
Dois-je passer l'identifiant de ma classe au constructeur ?
Utiliser une variable global pour l'instance de ma classe Mysql ?
Re,

En ce qui concerne la connexion à la base de données, il peut être intéressant de :
1. pouvoir acccéder à la connexion à n'importe quel endroit de ton projet, sans avoir à se demander si la classe de connexion est accessible ou non à tel ou tel endroit du code
2. ne pas avoir à recréer une nouvelle connexion à chaque fois qu'il faut faire une requête SQL

Le premier objectif peut être atteint en utilisant une classe statique. De cette façon, on ne passe jamais de classe de connexion en paramètre aux constructeur ou aux méthodes des objets : la connexion est accessible directement, à tout moment, de la façon suivante :
$connection =&Connection::getInstance();
Ici, getInstance est une méthode statique de la classe Connection et qui retourne une instance de connexion à la base de données.

Le 2eme objectif peut être atteint en faisant en sorte que la méthode getInstance() renvoit toujours la même connexion. Celle-ci n'est crée qu'une seule fois lors du premier appel à la méthode getInstance(), et réutilisée pour toutes les prochaines fois. Cela s'appele un Singleton en programmation. On peut l'écrire comme ceci :
class Connection{

     /*membre utilisé pour stocker statiquement une instance de Connection.*/
     private static $instance = null;

     /*on voit ici la particularité du Singleton : le constructeur est privé! Cela signifie
     que le dévelopeur ne peut pas créer lui même de nouvelle connexion : c'est de cette
     façon que l'on garantit que ce sera toujours la même connexion qui sera utilisée partout*/
     private function __construct(){
          //mettre ici le code pour se connecter à la base de données
     }

     /*la seule méthode publique qui permet de récupérer une connexion.
     Si aucune connexion n'a jamais été créée, $instance devient une nouvelle connexion,
     sinon c'est la connexion qui a été créée auparavant qui est retournée*/
     public static function &getInstance(){
     
          if( self::$instance === null )
               self::$instance = new Connection();

          return self::$instance;

     }

}
voilà, du coup dans la classe User, on peut accéder à la connexion unique sans avoir à la passer en paramètre au constructeur :
class User{

     public function __construct( $iduser ){

          //récupérer les données depuis la base

          $query = "SELECT * FROM `users` WHERE iduser = '" . intval( $iduser ) . "' LIMIT 1";
          $result = Connection::getInstance()->query( $query );
          ...

     }

}
@+