Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

GESTION UTILISATEUR/MEMBRE EN VERSION OBJET !


Information sur le tutorial

Catégorie :Class et Objet ( POO ) Date de création : 27/01/2006 00:00:04 Vu : 10 265 fois

Note :
9,8 / 10 - par 5 personnes
9,80 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (13)
Ajouter un commentaire et/ou une note

Description

Bon, tout le monde sait faire de la gestion de membres via des fonctions style ( if is_membre() ) qui teste si le niveau du membre est bien celui qu'on attend.
Eh bin, je vais faire la même chose, mais à ceci près que je vais le faire en orienté objet.
Je ne marque aucun code à l'interieur, seulement les grandes lignes !

Tutorial

Comment faire ca en objet ?
Voici le découpage qu'on peut établir entre un visiteur quelconque, un membre et un admin par exemple :

Visiteur --> |
                   | Membre
                   | Admin


Si on analyse le schéma (vite fait) du haut, on s'appercoit qu'être Membre ou Admin, on a quand même quelque chose en commun avec le fait d'être Visiteur. J'aurais pu pousser la chose plus loin comme ca :
Visiteur --> Membre --> Admin.

Qu'est ce que cela donne en objet alors...

Une classe abstraite User qui va contenir les infos d'un Visiteur standard.
Une classe héritière de User que je vais appeler Visiteur qui va ajouter des composantes de base d'un Visiteur standard (car on peut avoir plusieurs types de Visiteurs si on veut).

Une autre classe abstraite qui hérite de User, que je vais appeler MemberUser qui va prendre les infos initiales d'un Visiteur standard en lui rajoutant le fait que ce soit un membre qui est maintenant loggué.
Une classe héritière de MemberUser que je vais appeler Membre qui va ajouter des composantes d'un membre (car on peut aussi avoir plusieurs types de membres (genre Membre standard, Membre Club, Membre VIP etc...)

Une autre classe abstraite qui hérite de Member User (ou de User), que je vais appeler AdminUser qui va prendre les infos initiales d'un Visiteur standard en lui rajoutant le fait que c'est un membre de type Admin qui vient de se logguer.
Une classe héritière de AdminUser qui va ajouter des composantes que seul un Admin peut avoir accès (mais on peut aussi avoir plusieurs types d'admins spécifiques (admin niveau DIEU, admin bas niveau etc...)

Donc en relation objet, ca donne ca :
abstract class User {}
    |-> class Visiteur extends User {}
    |-> abstract class MemberUser extends User {}
              |-> class Member extends MemberUser {}
              |-> abstract class AdminUser extends MemberUser{}
                        |-> class Admin extends AdminUser{}

Voila la hierarchie des classes.
Maintenant rentrons plus dans le détail.
Nous allons donner un niveau de priorité pour chacun des personnes venant sur notre site.
0 correspondra à un Visiteur, 1 à un membre, 4 à un admin.

Donc, dans la classe abstraite User, je vais définir le niveau de mon visiteur à 0.
abstract class User {
  protected $level;
   public function __construct() {
     $this->level = 0;
   }
}

Pareil pour les autres :
abstract class MemberUser extends User {
  public function __construct() { // Surcharge du constructeur
    $this->level = 1;
}
abstract class AdminUser extends MemberUser {
  public function __construct() {
   $this->level = 4;
 }
}

Voila, on a défini nos bases de départ. Que reste t'il ensuite à faire ? Réussir à identifier notre visiteur pour savoir si il est membre ou admin ou simplement un visiteur. Il suffit pour cela d'utiliser les sessions. Lorsque votre visiteur se log, il suffira de remplir la superglobal $_SESSION[] et lui dire qu'il est loggué. De plus, il faudra s'assurer de garder les logins/levels de votre membre lors de l'identification pour pouvoir charger la bonne classe.

Et comment je peux utiliser ca ensuite ? Il faut encore rajouter quelque chose... Et oui, c'est pas tout de faire 40 classes si on peut pas les différencier lors de l'utilisation. Car :
$User = new Member;
ou
$User = new Visiteur;

Bah le script il sait pas trop faire la différence :p Donc il va falloir charger 3 méthodes en plus. Pour faire cela, je vais utiliser les interfaces qui sont arrivées grâce à PHP5.
Voici donc l'interface (très basique) que j'ai repris d'un membre de PHPCS d'une source il y a fort longtemps.
interface user_level {
  public function IsMember();
  public function IsAdmin();
}

Et voila c'est tout ! Il suffit juste de mettre l'interface dans les classes abstraites, ce qui évitera de recopier le code dans les classes héritières !
Et donc le modèle final sera de ce style : ( j'ai rajouté des méthodes histoire de bien démarquer les classes)

abstract class User implements user_level {
  protected $level;
   public function __construct() {
     $this->level = 0;
   }
   public function IsMember() {
    return FALSE;
   }
   public function IsAdmin() {
    return FALSE;
   }
  
}
class Visiteur extends User {

   public function __construct() {
    parent::__construct();
   }

   public function login($login, $password); // Tente un login.

   public function checklogin($login); // Pour vérifier si personne n'utilise ce login

}

abstract class MemberUser extends User implements user_level {
 
 protected $login;
 protected $email;

  public function __construct() { // Surcharge du constructeur
    $this->level = 1;
  }
   public function IsMember() {
    return TRUE;
   }
   public function IsAdmin() {
    return FALSE;
   }
}

class Member extends MemberUser {

  public function __construct() {
    parent::__construct();
  }

 public function modifieInfos(); // Permet de modifier ces infos dans la BDD
 public function recupererInfos(); // Permet de récupérer des infos

}


abstract class AdminUser extends MemberUser implements user_level {
  public function __construct() {
   $this->level = 4;
 }
   public function IsMember() {
    return TRUE;
   }
   public function IsAdmin() {
    return TRUE;
   }

}

class Admin extends AdminUser {

 public function __construct() {
  parent::__construct();
 }

 public function ChangeSiteInfo(); // permet de changer les infos du site

}

?>
Bref, les possibilités sont immenses après.
Il suffit après d'avoir instancier la bonne classe de faire un  if ( $User->IsMember() )  et hop, c'est automatique ! Plus besoin de charger à la main des fonctions spécifiques car tout est dans les classes !

Et si un jour je veux créer un type de membre spécifique ? Bah rien de plus facile, je ré-utilise ce que j'ai déja fait :

class MembreSpecifique extends MembreUser {

  public function __construct() {
    $this->level = 2; // Au lieu de 1;
  }

}

Et voila, vous avez votre nouveau type de membre avec des accès totalement nouveau. Si vous souhaitez simplement utiliser les mêmes accès qu'un membre standart mais en lui rajoutant des choses, il suffit d'hériter la classe de membre standard Member comme ca :

class MembreSpecifique extends Member {

 public function __construct() {
   $this->level = 2; // Je surcharge la méthode pour éviter de le mettre à 1
 }

}


Comme quoi, c'est tout simple. Après niveau vitesse, c'est sur que c'est un peu plus lent. Mais imaginez le fait que vous developpiez votre propre site d'un client, et qu'un jour ce même client vous demande de rajouter 2 accès membres avec fonctions totalements différentes et 3 accès admins avec certains pouvoir que n'ont pas les autres... je vous laisse le soin de tout coder de A à Z ! Je gagne prèsque 50% de mon temps avec la POO.

Voila les grandes lignes de la POO du coté de la gestion de membre... Si vous n'avez pas tout compris, posez des questions je suis la pour ca.
PS : je suis désolé pour la couleur, mais je verrais ca plus tard :)
signaler à un administrateur
Commentaire de malalam le 27/01/2006 10:47:48 administrateur CS

Joli ;-)

Je rajouterais une autre possibilité pour mise en place des droits, permettant d'avoir des utilisateurs d'un même niveau avec des possibilités légèrement différentes : le masque binaire. Chaque bit représentant un droit, à 0 on ne l'a pas, à 1 on l'a. Et une méthode canDo (string droit) vérifiant si l'utilisateur a ou non ce droit.

signaler à un administrateur
Commentaire de FhX le 28/01/2006 12:36:16

Voui, de toute facon y'a plein de possibilité de une mise en place des droits :)

signaler à un administrateur
Commentaire de kowal2205 le 04/03/2006 19:51:45

salut,

Pour avoir accès à "la bonne classe", comme tu le dis, tu passes systématiquement par un script PHP contenant l'ensemble des blocs IF ou bien a tu déjà testé une autre solution ?

j'envisage dans mon cas, avec par exemple quatre niveaux de responsabiltés pour une famille de classes, de mettre le nom de la classe à charger dans ma table utilisateur (MySQL).

signaler à un administrateur
Commentaire de FhX le 05/03/2006 13:52:30

Pas besoin ==>
PHP5 dispose d'une fonction d'autoload !
Il suffit que ton fichier s'appèle comme celui de la classe et t'as pas besoin de te faire chier à faire du require() pour choisir la classe nécessaire :)

signaler à un administrateur
Commentaire de hametsu21 le 21/04/2006 13:46:40

Je n'ai pas assimilé le passage ou tu expliques comment différencier les visiteurs.
Une personnes venant sur le site est visiteur, elle se logge, elle devient membre ou admin et possède des spécificités dans ses actions. Mais comment charger la bonne class ? car effectivement dans le code que mettre ? new member ? new user ? j'ai un peu décroché !

signaler à un administrateur
Commentaire de hametsu21 le 21/04/2006 22:14:22

<?php
include 'User.cls.php';

$User = new Visiteur(); // je suis visiteur
$User = new Member(); // je suis membre
$User = new Admin(); // je suis admin

if ($User -> IsMember()) {
if ($User -> IsAdmin()) {
echo 'vous etes admin';
}
else {
echo 'vous etes membre';
}
}
else {
echo 'vous etes visiteur';
}
?>

Voilà, j'ai un peu mieux compris, maintenant qu'est-ce qui fait que dans mon code se sera la class visiteur, membre ou admin qui sera instancié ? Ensuite, lorsque tu évoques les "fonctions spécéfiques" c'est comme supprimé des nouvelles ou en ajouter ? il faudrait donc rajouter les méthodes dans la class user ? et pourquoi faire un "if ( $User->IsMember() )" si justement les méthodes sont dans la class user ?

signaler à un administrateur
Commentaire de FhX le 23/04/2006 21:20:06

Ouh la oui, ca faisait longtemps ce truc la, va falloir que je retravaille ca :)

Pour pouvoir instancier la bonne classe, j'avais fait une classe statique en dehord de celle ci (vu qu'il ne me fallait qu'une seule instance de la classe, j'ai fais un Singleton externe) :

Class Instance {

static $_instance = NULL;
static $array = array('1'=> visiteur, '2' => membre); // etc..

public final static function GetInstance($level) {
    if ( !isset(self::$_instance) ) self::$_instance = new self::$array['level'];
   return self::$_instance;
}

}

Donc, lors du login ==> il suffit de récupérer le level du membre.
Une méthode parmis une autre :)

"Ensuite, lorsque tu évoques les "fonctions spécéfiques" c'est comme supprimé des nouvelles ou en ajouter ?" Exact oui :)
"il faudrait donc rajouter les méthodes dans la class user ?" Non, dans la classe admin... vu que seul un admin peut accéder aux nouvelles par exemple :)

"et pourquoi faire un "if ( $User->IsMember() )" si justement les méthodes sont dans la class user ?" Ca c'est moi qui est mal codé.
Tu peux faire comme ca pour éviter un if( $User->IsMember() ) :

Abstract class User {

  public function __call($name, $args) { // Signifie que tu appèles une méthode inconnu (genre un ajout de news que seul un admin peut avoir le droit)
     throw new Exception('Impossible d\'appeler '.$name.' => Accès refusé);
  }

}

Et ensuite, tu peux appeler directement les méthodes sans crainte :
try {
$User->AjouteNews();
} // SI un membre non autorisé tombe la dessus, il ne se passera rien du tout


Tu peux aussi bloquer tes pages admin :
try {
$User->AdminAccess();
} catch ( Exception $e ) {
  die ($e->getMessage);
}

Donc, il faudrait que ta classe admin possède la méthode AdminAccess() qui renvoit TRUE simplement alors que les autres classes membre et visiteur ne possèderont pas cette méthode ==> Exception.

Mais y'a encore des trucs à finaliser, dès que j'ai le temps je m'y remet :)

signaler à un administrateur
Commentaire de hametsu21 le 24/04/2006 10:22:38

Merci, car je code mon premier site et comme je suis un peu maniaque je vais toujours chercher plus loin, donc j'ai commencé à apprendre la poo, les xmlhttprequest, ect... pour fair un petit site de qualité...
Je ne savais pas comment gérer mes membres, au départ je pensait juste mettre un champ level dans ma table et le mettre dans une session $_SESSION['level'] que je comparerai à chaque action comme supprimer une news le level devrait être de 3 et s'il est inférieur refusé et redirection ect...
Mais cette méthode POO à l'air super intérressante.
Encore une question, au vus de ta classe news, tes méthodes pour supprimer/editer sont dedant, alors comment faire pour en être gérer avec cette class User ? faudrait les copier ou couper ? mais ça ferait un peu bordelique, je pensais faire les méthodes pour chaque "chose" dans leur "chose" respectif...
Bye, ;)

signaler à un administrateur
Commentaire de leo_ced le 10/05/2006 17:34:33

bonjour

je suis en train de travailler sur un site php/mysql et j'ai besoin d'aide
voila j'ai crée une base ou on peut ajouter des fiches projets identifiées par domaine
exemple fiche n°.... dans domaine .... avec les renseignement inherents a cette fiche

les modules d'ajouts et de suppression ... sont fait mais maintenant je voudrais que selon celui qui s'identifie on accede soit a un espace client soit a l'espace administration

en clair je ne sais pas si je dois creer deux tables (une pour l'administration avec login et password et l'autre client toujours avec login et password)

c'est la que je ne sais comment concevoir le "masque d'administration qui definira les differents droits des utilisateur
c'est a dire traiter et verifier les informations dans la base afin de diriger vers l'espace adequat

sachant que derriere je voudrais que selon les droits, l'administrateur ait acces a son espace (la c'est un redirect) mais le client aussi car il lui sera possible de telecharger des document mais que pour son domaine....
vous m'avez suivi?
je sais je suis embrouillé mais je ne vois pas pour le moment comment faire

bref help wanted!

loué soit celui qui m'orientera vers la bonne solution!!!!!

signaler à un administrateur
Commentaire de hametsu21 le 10/05/2006 17:56:28

Cette méthode est tout à fait valable,
Moi avec une unique table je récupère un champ 'level' qui me permet grâce au singleton d'instancier la bonne class.
Si c'est un visiteur, $level n'est pas définie, je le met donc à 0 et il m'instancie la class 'Visitor', un membre je met le level à 1 et les administrateurs à 5, cela m'instancie respectivement la class 'Member' et 'Administrator'.  Avec $user->isMember() ou $user->isAdministrator, je vérifie les accés aux fichiers. Avec la méthode de surchage magique des classes PHP __call je vérifie quand même que la méthode inconnu qui est appelé est adressé au bonne utilisateur.
Je suis entrain de faire une gestion grâce à ce tutorial très complète en POO avec fichiers d'exemples... je pense avoir finis d'ici la fin de semaine (je boss entre temps), peut-être pourrait-ce t'être utile...
A+

signaler à un administrateur
Commentaire de Florynth le 02/08/2006 04:34:10

Bonjour, moi ce que je fais c'est que en plus d'avoir des utilisateur j'ai des groupes d'utilisateurs. De base il y a

Groupes : WebUser, Administrator
Utilisateur : Guest, MainAdmin

Donc tout le monde et un WebUser et Guest est utilisé pour les gens qui ne sons pas loggué. Donc j'enregistre dans un variable le numéro d'utilisateur et si la variable est as null je la règle à celle de Guest. Il y a donc une table user une table group et une table group_user pour ajouté des utilisateur dans les groupes.

Les droit sont réglé de la façon suivante

Autorisé (TRUE): Refusé (FALSE): NULL

Par la suite il y deux tables : une pour les droits de groupe et l'autre pour les droits des utilisateurs.

Il y a une autre table qui contient toutes les commandes auquelle on veut vérifier les droits, il s'agit d'un id de commandes. Si on veut faire la gestion de plusieurs modules (exemple, faq, news, linklist) on peut toujours dans la table commande avoir un champ qui indique quel module aussi.

Bon si je vous ai pas perdu encore on continue.

Si je veux vérifié si un utilisateur à accès ou non a une commande voici ce que je fais.

Je vérifie si les droits de l'utilisateurs son réglé à FALSE, si c'est c'est le cas je retourne FALSE pour dire qu'il n'a pas droit.

Ensuite je trouve tout les groupes auquelle l'utilisateur fait partie.

Si il y a UN groupe qui est réglé à FALSE je retourne FALSE.

Donc on vient de vérifier si l'utilisateur ou un group auquel il appartien l'empêche d'accèdé à un module/commande.

Deuxième étape.

Je fais la même chose mais pour vérifier si l'utilisateur ou UN des groupes est réglé à TRUE si c'est le cas je retourne TRUE.

La vous me demandé à quoi sert de mettre un droit à NULL et bien si ni l'utilisateur ou les groupes auquelles il appartien n'a donné accès à la commande (tous à NULL) on retour FALSE.

Comment ça s'utilise

Exemple le modules de gestion des nouvelles. Trois commandes

Ajouter/Supprimer/Voir

(Group) WebUser : NULL/NULL/TRUE
(Group) Administrator : TRUE/TRUE/TRUE

(User)Guest : NULL/NULL/NULL
(User)MainAdministrator: NULL/NULL/NULL

Donc un Guest va voir la nouvelles car il fait partie du groupe WebUser qui à le droit.

Le MainAdministrator aura accès à tout car il fait partie de Administrator qui à accès à tout.

Maitenant je veux un administrateur qui peu ajouter des nouvelles les voirs mais pas les supprimers.

(User)Administrateur1 : NULL/FALSE/NULL

Puisqu'il fait partie de Administrator il a accès à tout sauf à Supprimer car sont propre droit est réglé à FALSE.

Quand utilisé

(User)Administrateur1 : NULL/FALSE/TRUE

Et bien si on ne veux plus que les membre de (Group)Administrator est accès à lire (bon demandé moi pas pourquoi) on va réglé (Group)Administrator à : TRUE/TRUE/NULL

Mais la (User)Administrateur1 va toujours y avoir accès car lui il est réglé à (NULL/FALSE/TRUE) Mais pas (User)MainAdministrator (NULL/NULL/NULL)

Maintenant pire encore on veut en plus refusé l'accès à tous les membres (Group)Administrator à Supprimer on règles alors (TRUE/NULL/FALSE)

Toutes les membres du groups peux importe leurs propres droits n'auront pas le droit à Supprimer une Nouvelles car il fait partie d'au moins UN groupe qui lui refusé l'accès (FALSE).

Lors de gros projet réglè les droits par module (News,Faq)

(Group)WebUser (NULL/NULL/TRUE),(NULL/NULL/TRUE)
(Group)Administrator(TRUE/TRUE/TRUE),(TRUE/TRUE/TRUE)
(Group)NewsAdministrator (TRUE/TRUE/TRUE),(NULL/NULL/NULL)
(Group)FaqAdministrator (NULL/NULL/NULL),(TRUE/TRUE/TRUE)

(User)MainAdmin Membre de (Group)Administrator
(User)Admin1 Membre de (Group)NewsAdministrator,(Group)WebUser
(User)Admin2 Membre de (Group)FaqAdministrator,(Group)WebUser

Donc MainAdmin à accès à tout, Admin1 seulement au News et Admin2 à la FAQ.

Il pouront tous Voir la faq/new car ils sont membre de (Group)WebUser


Trucs et Astuces.

Un utilisateur précis (ex MainAdministrator) a toujours accès à tous pour s'en assurer dans vos tests de droit vous faite

SI UserName = MainAdministrator RETURN TRUE

Donc peux importe les droit que vous réglé au groupe il aura toujours accès. Vous donnez ce droit seulement à la personne qui gère le site au complet, à l'occurance VOUS.

Maitenant il faut faire le module de gestion des droits pour changé les droits la ça se corse encore plus et je n'ai pas finis de réfléchir à ça, faut évité qu'un Administrator qui peux créé des Utilisateurs créé un Utilisateurs et lui donne plus de droit qu'à lui même car il pourrait se créé un compte avec plus de Privilèges et ainsi on pert la gestion des droits des Admin. Reste toujours la possibilité qu'il n'y ai que le MainAdmin qui puisse changé les droits mais ça enlève des possibilité, exemple qu'un Admin de module de Forum puisse lui même créé de Modérateur sans passé par le MainAdmin....

Bon j'ai écris ça en 1 heure une nuit pendant que j'étais pas capable de dormir, j'ai fait le module il y a maintenant 2 semaines mais c'est la première fois que je l'explique!

Si ça intéresse les gens je vais prendre la peine de mieux structuré (avec votre aide, je sais que je peux être compliqué) et vous donnez les structures de tables MySQL ainsi que les contraintes...

Si ça intéresse personne et bien je vais le gardé pour moi :O)

Martin

signaler à un administrateur
Commentaire de Florynth le 25/11/2006 15:20:38

Puisque plusieurs personne m'ont demandé plus de détails je vais travaillé sur un tuto plus présentable de ce que j'ai dit plus haut. Donné moi quand même du temps (quelques semaines) et je vous fais signe quand c'est prêts.

signaler à un administrateur
Commentaire de shidame le 16/03/2007 17:27:09

Bonjour, je sais que cela fait un bon moment que ce tuto a été posté mais bon j'y tombe dessus que maintenant.

Alors ma question est la suivante : a quoi sert ici l'interface user_level, ne peut ont pas simplement placer les methodes isAdmin() et isMember() dans les classes abstraites ??

Autre question qui me vient au moment où je tape ce message : une methode AjouterNews() dans la classe Admin consisterai à instancier une classe News ainsi qu'à appeler $news->addNews() par exemple , je ne sais pas si je suis très clair (je débute en POO et j'avoue avoir du mal ^^).
Pour reprendre la question de façon plus générique comment articuler ce type de classe avec une classe de gestion des news ?

Merci par avance,

Ajouter un commentaire



Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,094 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.