Bonjour,

Voila plusieurs jours que je n'arrive pas à trouver la meilleure solution.
J'ai actuellement sur mon site cakePHP une table Users qui contient certains champs globaux (username,pwd,rang,adresse...) puis d'autres champs spécifiques à un type d'user qu'on appellera "agent".
Il se trouve que je dois maintenant creer 2 autres types d'users, qui sont "visiteur" et "informaticien" qui partagent les champs globaux , mais ont des champs spécifiques....
En gros dans mon modele de données les tables agent,visiteur et informaticien hériteraient de "user" mais dans cakePHP je ne vois pas comment faire cela, de manière la plus optimale et que je puisse rajouter autant de "rôle" que je souhaite par la suite. Déja dans un premier temps creer les 3 tables, avec dans chaque table une clef étrangère user_id ?

J'ai vu sur certains site une histoire de redéfinir AuthComponent::Identity() ?

Je n'arrive pas à voir clairement vers quelle solution me diriger.... avez vous une idée??

Merci d'avance.

20 réponses


Pourquoi ne pas faire une table Category_User liée à ta table User ?

jey1985
Auteur

heuu je ne vois pas ce que ça apporterais en fait?
Le mécanisme de login/logout du UsersController deviendrais quoi ?

Bonjour.

heuu je ne vois pas ce que ça apporterais en fait?
Le mécanisme de login/logout du UsersController deviendrais quoi ?

Quel est le rapport avec le système d'authentification ?
Est-ce qu'un utilisateur a besoin d'avoir un role ou d'appartenir à un groupe spécifique ou autre pour se connecter sur ton système ?

jey1985
Auteur

Bonsoir,
non du moment qu'il a un username/password il peut.
Mais c'est la manière de répartir les informations à stocker par type d'utilisateur qui m'embete... j'aimerai faire au plus éfficace, mais je ne sais pas trop comment

Prenons un exemple simple, j'ai 3 tables:

users(id,username,password,role)
mandataires(id,secteur,agence)
gestionnaires(id,codepro,url)

Je creer un user dont le role est mandataire, et je veux lorsqu'il se log avoir accés à ces infos qui sont dans la table Users et automatiquement à ces infos correspondantes à ce qu'il y a dans la table mandataire.
Maintenant si c'est le gestionnaire qui se log, idem je veux les infos de Users et aussi les infos qu'il y a dans gestionnaire.
Forcément idem pour les saves...

Je me demande s'il y a un moyen "simple" de faire ça plus ou moins automatiquement... ou je suis obligé de mettre une clef étrangere user_id dans mandataire et gestionnaire et faire en fonction de si le tableau remonté est vide?

Tout dépend de ce que tu veux, si tu n'as que mandataires et gestionnaires, effectivement le plus 'simple' serait le user_id dans chaque table. Maintenant si tu souhaites élargir les rôles se sera contraignant de refaire à chaque fois une nouvelle table

Le plus simple, selon moi, serait une table User, Role, FeaturesRole avec les relations suivantes

USER HasOne (HasMany?) Role
Role HasOne FeaturesRole

Après en faisant un simple User->find tu récupéreras toutes les données que tu veux (role, Features)

jey1985
Auteur

Oui effectivement, par la suite je souhaite pouvoir stocker d'autres rôles...
Avec ce systeme là, dans FeaturesRole, je suis obligé de stocker en vrac les infos mélangé de tous les rôles du coup ?

Tu n'es pas obligé de mélanger les infos de tous les rôles. Si tu es à l'aise avec les liasions CakePHP, tu peux faire une relation HABTM entre la table Rôle et FEATURES :

USER HasOne ROLE
ROLE HABTM FEATURES

Bonjour,

Ayant eu affaire à la même contrainte il y a peu, je te conseille d'avoir une table "Users" standard qui englobe les données partagées par les utilisateurs et des tables spécifiques pour chaque type d'utilisateurs. Tu auras :

Table users (id, username, password, etc.)
Table mandataires (user_id, champ1, champ2, etc.)
Table gestionnaires (user_id, champ1, champ2, etc.)

Ton ID primaire sur les tables secondaires sera ton "user_id" (en la définissant dans ton model avec primaryKey) et elles seront liées en "hasMany" avec la table "Users". Et au niveau de ta table "Users" tu auras des "hasOne" avec dependant à "true" avec tes tables secondaires.

J'espère m'être fait comprendre !

jey1985
Auteur

Bonjour Wa3aR,
donc ce qui veut dire que quand je vais faire un $user=$this->User->find("first"...)
J'aurai un truc du genre:

array('User'=> array("id"=>xx,
                                     "username"=>xxx
                                     "password"=>xxx),
            'mandataires'=>array(),
            'gestionnaires'=>array("id"=>xx,
                                                    "champ1"...)
    );

Ce qui voudrait dire dans ce cas là que c'est un User de type gestionnaire.

ok pour le find, ce qui est plus embettant c'est pour le save() je vais devoir faire des switch pour sauver dans la bonne table..ce qui peut devenir contraignant si je rajoute des tables de rôles...

massadu33, ta table features contiendrais donc 3 colonnes, id,fieldName,fieldVal ? Du coup avec ce système je sors complétement du framework cakePHP puisque pour éditer un formulaire je vais être embêté pour lui passer les data sauvegardées par exemple ?

Perso, je ne travaille pas avec la table "Users" par la suite vu que celle-ci est accessible avec le "Auth". Je travaille directement avec le model "secondaires" qui dans ton cas seront les gestionnaires et mandataitres (tu auras donc $this->Gestionnaires->find ...).

jey1985
Auteur

Donc tu te sers de la table Users uniquement pour le loging/logout si je comprend bien ? et les informations partagées qui se trouve aussi dans Users tu y accedes comment?

Bonsoir.

Donc tu te sers de la table Users uniquement pour le loging/logout si je comprend bien ?

Pas forcément seulement pour la connexion, ça peut être pour des tokens pour la validation du compte par exemple et d'autres trucs, mais d'après son explication c'est surtout pour tout ce qui concerne le compte de l'utilisateur et non pour les informations personnelles supplémentaires.

Tu pourrais par exemple faire quelque chose comme ça » ici.

Pour une brève explication :
La table features regroupe les champs que tu veux définir, comme par exemple : secteur, agence, codepro, url, etc..), ensuite avec l'association sur les tables features_groups et groups, tu peux dire que tel champ est assigné à tel groupe, voir plusieurs.
Concernant la table details, c'est la liste avec les valeurs associées entre l'utilisateur et un enregistrement de la table features.
Donc avec cette composition, tu peux administrer les champs (ajouter/supprimer) tout en les assignant à tel groupe ou tels groupes.
Il te suffit par la suite sur la page d'édition de l'utilisateur de faire une boucle sur les enregistrements qui seront retournés par la table features dont les enregistrements seront bien sur ceux sur lesquels l'utilisateur à le droit d'éditer.
Si par exemple dans les groupes tu as mis Gestionnaire et Mandataire, que tu as assigné les champs qui leurs sont attribués, un utilisateur du groupe Gestionnaire va sur sa page d'édition, il n'aura de lister que les enregistrementscodepro et url (plus les autres que tu as assigné à son groupe).
Dans la table features sur le schema j'ai défini des champs supplémentaires de manière à pouvoir les utiliser dans la génération des inputs, de manière à ce que ce soit cohérent avec le genre de données que tu veux que ton utilisateur saisisse, plus d'autres champs que tu peux facilement comprendre en lisant leurs noms.

jey1985
Auteur

Bonsoir,
Je comprends mieux ta solution, elle me parait vraiment pas mal, surtout paramétrable à souhait. Ce qui me fait un peu peur, c'est de devoir tout casser ce qui existe actuellement surtout pour mes vues/actions add et edit, en revanche l'avantage c'est qu'une fois mes vues modifiées, quel que soit le rôle, j'aurais pas besoin de creer de nouvelles vues.

Je sais pas ce que tu en penses, mais pour le reste du site, je peux peut-etre m'en sortir en définissant dans le User::afterFind(), une méthode qui pour chaque ligne de User['details'] remet le couple field/value dans User['User'] comme ça jsuis sur que par tout ailleur où j'utilise des datas qui on été déplacés dans features, il n'y aura pas de bug...?

ps: moi qui comptait mettre en place les ACL dans une future version, j'ai l'impression qu'avec ce systeme on s'en inspire :)

jey1985
Auteur

Bonsoir,
du coup je sais pas si c'est une bonne pratique de remettre toutes les features dans l'array User, dans un afterfind ? perfo... tout ça ?

jey1985
Auteur

Salut à tous,
j'ai donc essayé de mettre en place ce système, mais je me retrouve avec un probleme, en effet dans ma table initiale Users, j'ai plein de clef étrangères, sector_id, region_id, parain_id etc... qui pointent sur d'autre table.
Et du coup avec ce système là, je perds le bénéfice des relations cakePHP il me semble ? a moins qu'on puisse faire différement?

bonne soirée

si tu veux faire différents type d'utilisateur mais ayant des spécifications dans un domaine je ne vois que ça =)

jey1985
Auteur

rahhh jsuis deg lol !! c'était tellement cool de pouvoir rajouter des champs dynamiquement ... bon tant pis
je vais stocker tous mes champs dans ma big table et essayer de modifier les critères de "validation" du model User pour que dans certains cas , certains champs ne soient pas obligatoire et dans d'autre cas oui.. qu'en pensez vous ?

après tu peux peut-être le faire dynamiquement =) tu veux parler des expressions régulières ? =)

jey1985
Auteur

Bonjour
Non je veux parler que dans la même table je vais par exemple stocker
-username
-password
-type
-num_rcpro => (champ propre au type d'utilisateur 1 )
-voiture => (champ propre au type d'utilisateur 2)

Actuellement dans mon modele User, dans mes regles de validation j'oblige l'utilisateur à renseigner "num_rcpro"
mais sauf que si on est en train de saisir un utilisateur de type 2 , je veux rendre num_rcpro non obligatoire et rendre voiture obligatoire en revanche.
Doonc je me demandais s'il y avait moyen de faire un switch sur des regles de validation en fonction d'un champ, ici "type"

jey1985
Auteur

Je crois que j'ai trouvé la solution,
if ($this->User->validates(array('fieldList' => array('email', 'password')))) {
// valid
} else {
// invalid
}

dans un cas je valide les champs concernant le type 1 et dans un autre cas je valide les champs concernant le type 2
qu'en pensez vous ?