Bonjour à tous,
Voilà une bonne semaine que je me casse les dents sur ce component qui est pourtant très pratique. Ma problématique de base est que j'ai plusieurs tables d'utilisateur (students, teachers, admins) qui ont des champs différents et tout.
J'ai trouvé une "solution" pour résoudre en partie ce problème. Je voudrai aussi que l'authentification se passe sur le même controler donc j'ai choisi de réutiliser UsersController pour ça.
Le problème que j'ai est que lorsque je change dans $component le userModel, le conponent ne marche plus. Il ne fait plus de requête en BDD et ce même quand je n'utilise pas mon histoire de multi table. Si par exemple je lui dit juste que tout les utilisateurs sont enregistrés dans Student, rien ne marche et ce même si l'authentification se passe dans le controller Users ou Student...
Mon code :
AppController.php
public $components = [
'Session',
// ** la config de Auth si j'utilise des tables multi utilisateurs **
// 'Auth' => [
// 'authenticate' => [
// 'StudentModel' => [
// 'userModel' => 'Student',
// 'fields' => [
// 'username' => 'mail'
// ]
// ],
// 'TeacherModel' => [
// 'userModel' => 'Teacher',
// 'fields' => [
// 'username' => 'mail'
// ]
// ],
// 'AdminModel' => [
// 'userModel' => 'AdminUser',
// 'fields' => [
// 'username' => 'mail'
// ]
// ]
// ]
// ]
'Auth' => [
'authenticate' => [
'Form' => [
'userModel' => 'Student',
'fields' => [
'username' => 'mail'
]
]
]
]
];
UsersController.php
<?php
class UsersController extends AppController {
// Pour que le controller n'utilise pas de model User
var $uses = [];
public function login() {
$this->loadModel('Student');
$this->loadModel('Teacher');
$this->loadModel('AdminUser');
if ($this->request->is('post')) {
debug($this->request->data);
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirectUrl());
}
else {
$this->Session->setFlash(
__('Username ou password est incorrect'),
'default',
array(),
'auth'
);
}
}
}
public function logout() {
$this->Auth->logout();
return $this->redirect('/');
}
}
J'espère avoir été assez clair dans mon problème ^^'
Merci d'avance pour vos réponses =)
J'ai du faire face au même problème que toi il y a quelques temps. Tu devrais pouvoir y arriver en utilisant ta méthode (vérifies que tu ais les bons champs dans les autres modeles de User : mail, username, password).
Sinon voilà comment moi j'ai procédé et ce n'est pas une mauvaise pratique, juste séparer la logique appli de la logique métier :
Un User est pour moi un utilisateur du site/appli, toute la connection est faite ici avec un couple email/mot de passe.
Un User peut avoir différents profils, comme Student ou Teacher ou les deux. Donc mon modèle a un champ teacher_id et student_id qui sont NULL par défaut.
Lorsque l'User se connecte, il est très simple de savoir si c'est un Student ou un Teacher ou les deux.
Si un User se barre de l'appli et supprime son profil, les données de Student ou Teacher sont conservées (tu peux garder un historique).
Bonjour.
Ce serait bien que tu donnes un peu plus de précisions, car, que ce soit lorsque tu utilises un unique système d'identification ou un multiple, est-ce que tu utilises bien un mot de passe pour chacun ?
Ensuite, dans le code que tu nous donne, tu donnes un tableau vide dans la variable $uses, ensuite tu charges 3 modèles dans la fonction login (alors que tu ne t'en sert pas, sauf à la rigueur le modèle Student), mais pourrais-tu nous en dire plus, concernant par exemple la requête qui est effectuée par le composant Auth lors de la fonction login ?
Si tu ne nous donne pas plus de détails, je ne vois pas trop comment nous pourrons t'aider.
Ensuite, est-il vraiment nécessaire que tu utilises plusieurs modèles pour l'identification, alors qu'à priori c'est juste pour faire une distinction entre différents types d'utilisateurs, alors qu'un simple champ, un système de rôle en gros dans une table permettrait de faire la différence entre chacun ?
Bonjour,
Tout d'abord merci pour vos réponses et voici quelques précisions =p
J'ai donc 3 tables différentes pour les utilisateurs suivant leur statut : students, teachers et admins. Chacune de ces tables à au moins un champ mail et password et celui-ci contient bien des mots de passe cryptés par Auth pour chaque utilisateur.
Ce que je voudrai faire est qu'Auth regarde dans ces 3 tables au lieu d'une unique table users et que la connection pour tout les utilisateurs se passe sur la même page, donc users/login.
Je n'ai pas de table users en BDD et c'est donc pour ça que j'utilise la ligne var $uses = []; Et qu'ensuite je charge les models Student, Teacher et Admin.
En fait mon problème n'est pas tellement cette histoire de multi table, c'est juste que je n'arrive pas à dire à Auth de vérifier mes utilisateurs dans une autre table que users... Partout j'ai vu qu'il fallait utiliser l'option userModel mais lorsque je l'utilise je ne vois plus aucune requête BDD de la part de Cake. Je ne sais même pas si ma solution pour gérer le multi table est bonne car je suis bloqué par ce simple soucie =/
Comme j'avais des problèmes avec ça, pour tester j'ai restreint à n'utiliser que le model Student mais le problème est toujours là ! (c'est pour ça que je charge tout les models, j'aurai dû les commenter pour vous les montrer ^^')
Utiliser une table users et ensuite faire référence à la table suivant son profil j'y ai pensé mais je ne trouve pas ça "propre". Ça voudrai dire que dans ma table users j'ai un mail, un password, un student_id, un teacher_id et un admin_id sachant qu'en plus un utilisateur n'appartient qu'à un seul profil. Voilà pourquoi je me suis tourné vers 3 tables distinctes.
J'espère que c'est plus clair maintenant ^^
Bonjour,
Au niveau de la modélisation de ta base de données, tu pourrais peut être faire quelque chose dans ce style là au lieu d'ajouter un student_id, et un teacher_id ...
Users =>
- id
- username
- password
- email
- role_id
Roles =>
- id
- name
Ect ....
Comme ça, tu pourrais avoir une table où il y a tout les utilisateurs qui font référence à un rôle. Les rôles seront dans ton cas "Student", "Teacher" et "Admin".
Ensuite, à voir ce que tu veux faire, si tu veux stocker des infos différentes en fonction du "role" etc...
Ça peut être une piste à approfondir :)
@PallMallShow
J'y ai aussi pensé ^^ Mais j'ai peur de cette solution avec CakePHP. Comme il utilise l'auto_increment pour les id de chaque table, les id vont se chevaucher entre les tables des utilisateurs. Il faudrait que fasse tout un système pour qu'il génère un id propre à chaque table d'utilisateur, et j'ai peur que Cake perde son automatisation et que je perde plus de temps qu'autre chose.
C'est vrai ça simplifierait les choses avec Auth mais peut-être pas pour le reste. J'ai quelques données en communs entre les tables pour pouvoir les regrouper.
Même si cette solution peut convenir j'aimerai vraiment savoir pourquoi ce userModel ne marche pas... Ça pas l'air si compliqué pourtant ! =o
Ah oui je ne l'ai pas dit mais je débute avec CakePHP ;)
Il faut aussi penser à la suite, si tu as une structure comme ca, tu es censé pouvoir tout récupérer à chaque fois (avec les liaisons entr les tables, les container ....).
A confirmer par les copains qui passeront ici, mais je pense que c'est une solution qui d'une part, résoudrais ton soucis, et d'une autre qui fonctionnerai partout, que demander de plus ! En plus la modélisation est pas si moche que ça, tu y retrouve une certaine hierarchie.
Imagine, demain, tu veux un autre rôle, je dis une bétise, mais par exemple "Student parent". Tu va modifier toutes tes tables pour correspondre à celui là en plus ?
Alors que si tu fait avec une table User, Role et tout ça, un simple entrée en plus dans la table Role, et ça roule !
Bonjour.
Comme je le pensais c'est bien pour faire une distinction entre différents types d'utilisateurs.
Comme il utilise l'auto_increment pour les id de chaque table, les id vont se chevaucher entre les tables des utilisateurs
Je ne vois pas quel est le problème que tu pourrais rencontrer avec l'auto-incrémentation des champs id, le champs de la table users ne posera aucun soucis concernant les identifiants de sessions, si tu utilises l'exemple de PallMallShow.
De plus, que pour voir quel genre d'utilisateur il s'agit lors de la connexion d'un d'entre eux, avec ton système de 3 tables, tu devras faire une requête sur 3 tables, alors qu'avec le système des 2 tables, tu auras juste à faire une requête sur la table users avec une jointure via le Composant Containable par exemple, voir par la même occasion, une liaison avec la table spécifique concernant le rôle de l'utilisateur récupéré, tu gagneras déja de cette manière niveau performance, surtout que si tu as des informations précises à récupérer sur la table liée au rôle de l'utilisateur, tu peux directement préciser les champs via la liaison dans les modèles concernés.
Car si par exemple dans la table teachers tu as genre 6 champs à récupérer, contrairement à la table student où tu n'en aurait que 2, cela te permettra d'éviter des champs inutiles lors des requêtes à chaque connexion.
Je ne sais pas si tu vois ce que je veux dire actuellement, mais tu verras qu'au long terme, tu finiras par en comprendre l'importance.
De plus, qu'avec tes 3 chargements de modèles différents, tu fais quand même faire une certaine surcharge à ton application pour pas grand chose.
Utiliser une table users et ensuite faire référence à la table suivant son profil j'y ai pensé mais je ne trouve pas ça "propre"
C'est pourtant la solution qui génère le moins de requêtes. Par contre requêter 3 tables pour loguer un utilisateur, ça c'est pas très propre.
Salut, salut
J'avoue qu'une table Users m'arrangerai mais je ne vois pas trop comment faire. PallMallShow tu proposes que users fasse référence à une table roles mais que va-t-elle m'apporter ? J'ai besoin de pointer sur une table particulière suivant le profil de mon utilisateur car les données diffèrents suivant le profil.
Du coup avec cette table users comment faire pour la lier à la table de son profil. J'avais pensé à deux solutions :
- Soit j'ai un champ qui fait référence à un id, mais pour celà il faudrait changer la forme de l'id de chaque table profil pour pourvoir les distinguer entre elles (la table profil_students avec un id de la forme Sxxx et la table profil_teachers avec id de la forme Txxx, etc).
Désaventage : Je suis obligé et modifier la génération id pour ne plus utiliser l'auto_increment qui lui ne donne que des numéros sans distinction de la table. De plus il faut quand même analyser l'id pour savoir dans quelle table profil chercher.
- Soit je fais un champ profil dans users qui me dit dans quelle table chercher l'utilisateur (si profil = 'student' alors chercher son profil dans la table profil_students).
Désaventages : Je vais devoir analyser le champ pour savoir quelle table de profil chercher.
Bref ça me parrait pas top, mais je me trompe peut-être. J'ai du mal à comprendre comment lier ces tables proprement, et pourtant j'ai l'impression que ça vous semble pas si compliqué ^^' Il y a un truc que je ne dois pas saisir.
@Lartak : Je n'ai pas eu le temps de voir ce qu'était le Contenable (préparer Noël et ce site c'est la galère...), si j'ai bien compris ça permet de faire des filtres sur tes requêtes et gagner en performance ?
Sinon à part mon histoire de multi table, pourquoi userModel de Auth ne marche pas ??? Je souhaite vraiment trouver la réponse ^^'
Bonne fête à tous ! (°^.^)°
Bonsoir.
En gros oui, c'est plutôt pour "faciliter" au niveau des associations entre les modèles, tout en pouvant contrôler plus efficacement les profondeurs utilisées dans celles-ci.
Tu te trompe, tu n'as aucune id à préciser, tu fais ta table profil selon le schéma standard, exemple :
- id
...
- user_id
Le dernier champ permettra de faire la liaison entre a table users et la table profiles
Ensuite tu défini une association entre ta table users et ta table roles.
Je ne vois vraiment pas en quoi tu te complique les choses, tu peux largement laisser l'auto-incrément de l'id dans ta table profiles.
Ensuite, ce que je t'ai expliqué dans mon post précédent, c'était juste un exemple vite fait, normalement juste avec ces 3 tables (la table roles peut même être évitée, si tu peux définir les rôles des utilisateurs dès le départ, et qu'ils ne sont pas censés être modifiés par la suite, en gros, s'ils sont constants)
Seulement avec les tables users et profiles, tu peux faire ton système de connexion et de distinction des 3 types d'utilisateurs.
Hello !
Bon j'ai suivi vos conseils et j'ai fait une table users à part et qui après hérite d'une autre table suivant son profil. Ça marche bien pour l'instant ;)
Donc merci pour vos conseils.
Par contre je ne mets pas le sujet résolut car je me répète mais ma question de base était de savoir pourquoi l'option userModel ne fonctionnait pas.
Merci encore
De mémoire, je crois que quand tu changes la convention du userModel, tu dois obligatoirement spécifier les champs username et password
'Form' => [
'userModel' => 'Student',
'fields' => [
'username' => 'mail',
'password'=>'password'
]
]
Malheureusement ça n'a pas l'air d'être ça. Par contre si je fais loginAction vers students/login en plus ça marche... Mais pas si je reste sur le controller Users
Bonsoir.
Par contre je ne mets pas le sujet résolut car je me répète mais ma question de base était de savoir pourquoi l'option userModel ne fonctionnait pas.
L'option userModel, fonctionne parfaitement, après selon les définitions qui peuvent être faite dans l'appplication ou l'utilisation qui en est faite dans l'application, il peut y avoir des précisions à donner à ton application, mais ça, nous ne pouvons pas le faire où le deviner à ta place.
Malheureusement ça n'a pas l'air d'être ça. Par contre si je fais loginAction vers students/login en plus ça marche... Mais pas si je reste sur le controller Users
Si tu utilises le modèle User (donc la table users) et le controller Users, tu n'a pas à définir le userModel, étant donné que tu suis les conventions de base de CakePHP.