Bonjour,

Voilà, je développe mon site avec CakePHP et je bloque sur un truc.

J'ai une table « user » avecc un id, username, password ...etc
Et une table « match » avec user_1 et user_2.

Mais je n'arrive pas à lier les models correspondant pour effectuer correctement mes requêtes.

Merci de votre aide ;)

15 réponses


http://book.cakephp.org/2.0/fr/models/associations-linking-models-together.html

Salut, ce lien peut surement t'aider. Si tu veux d'autres informations, il va nous falloir les controllers et les models.

Bonne continuation.

DexX
Auteur

Bien, voilà mon model « User » :

<?php 
class User extends AppModel {
    public $useTable = 'user';
    public $recursive = -1;
    public $hasMany = 'Post, Messaging';

Mon controller « Match » :

public $hasMany = array(
        'Match' => array(
            'className' => 'Match',
            'foreignKey' => false,
            'conditions' => array(
                'OR' => array(
                    array('Match.user_1' => '{$ __cakeID__ $}'),
                    array('Match.user_2' => '{$ __cakeID__ $}')
                )
            ),
        )
    );

Le résultat du debug de ma variable passé à ma vue :

Array
(
    [0] => Array
        (
            [Match] => Array
                (
                    [id] => 1
                    [championship_id] => 1
                    [user_1] => 1
                    [user_2] => 2
                    [type] => Aller
                    [jouer] => 1
                    [score_user_1] => 1
                    [score_user_2] => 2
                    [winner] => 2
                    [date] => 2013-04-11
                    [valid_user_1] => 1
                    [valid_user_2] => 1
                )
        )
)

J'aimerais que sa m'affiche aussi les informations sur les deux utilisateurs (user_1 et user_2).
Pour cela je dois lier mes models (?).

Merci de votre aide ;)

Oui tu dois lier tes modèles. D'ailleurs, il y a un cas assez similaire au tien à ce lien :

http://stackoverflow.com/questions/6087684/cakephp-model-relationship-with-multiple-foreign-keys

Ps : il me semble que la récursivité se fait dans le controller/ comme le usestable

DexX
Auteur

Oui, j'ai lu ce topic mais je ne vois pas à quoi correspond « HomeMatch » et « AwayMatch ». Je comprend ce que c'est mais pourquoi le déclarer ainsi ? Je ne voie pas comment l'appliquer à mon code.

home match, c'est l'équipe qui reçois et away match c'est euh comment on dis... les visiteurs ce qui est équivalent user_1 et user_2 pour toi. Mais tu as le même code que la réponse, donc je pense que tu la lu ^^'

si j'ai bien compris le lien =)

dans ton model user

public $hasMany = array(
    'Match' => array(
        'className' => 'Match',
        'foreignKey' => false,
        'conditions' => array(
            'OR' => array(
                array('Match.home_team_id' => '{$ __cakeID__ $}'),
                array('Match.away_team_id' => '{$ __cakeID__ $}')
            )
        ),
    )
);

un belongs to dans le model user

dans ton controller match

public $uses=array('Match','User');

une recursive à 1 dans la fonction de la vue.

Ensuite remets moi le sql dumper pour voir si y a eu les modification =)

DexX
Auteur

sql dump :

SELECT `Match`.`id`, `Match`.`championship_id`, `Match`.`user_1`, `Match`.`user_2`, `Match`.`type`, `Match`.`jouer`, `Match`.`score_user_1`, `Match`.`score_user_2`, `Match`.`winner`, `Match`.`date`, `Match`.`valid_user_1`, `Match`.`valid_user_2` FROM `match` AS `Match` WHERE `Match`.`championship_id` = 1 AND `Match`.`jouer` = '1' AND `Match`.`valid_user_1` = 1 AND `Match`.`valid_user_2` = 1

Je rappelle que je suis dans mon controller Championship.

"Je rappelle que je suis dans mon controller Championship."

Oo euh, j'ai loupé un épisode... Pourquoi tant de haine :'(

Tu récupère bien les matchs so ?
fais un load model dans la fonction de ta vue. Tu pourras récupéré tes informations utilisateur via une condition avec user_1 et user_2. mais bon la liaison sert plus à grand chose :p

DexX
Auteur

Bien, je m'explique.

Dans ma vue « Championship/show », j'affiche un tableau avec les derniers résultats.
Je récupère donc tous les matchs en fonction du championnat (championship_id).

J'aimerais lier mes modèles « Match » et « User » de façon à ce quand je récupère les matchs, je récupère aussi le nom de l'utilisateur.
Et dans ma table match, mes utilisateurs sont « user_1 » et « user_2 ».
En liant les modèles comme dans la documentation, il me demande de créer le champ « user_id ».
J'aimerais donc savoir comment lier mes modèles pour récupérer le nom de l'utilisateur en fonction de l'id (« user_1 » et « user_2 »).

Je ne sais pas si tu as trouvé une solution mais a froid je te proposes ca:

Faire un HABTM entre Match et User

Grace à cela tu pourras stocker les infos du match dans Match, les infos de chaque joueur dans User (chose classique ...)

Et en faisant un HABTM entre les 2 tables tu lies plusieurs user à plusieurs Match, et donc tu pourras récupérer chaque info désiré dans chaque table grâce à la liaison des 2.

PS: Tu pourras même faire évoluer par la suite ton système sans restriction de nombre de joueur par match :)

DexX
Auteur

D'accord merci et aurais-tu un exemple de la façon dont on met en place un HABTM ?

je te renvoi vers un tuto de Grafikart a ce sujet. Mais tu verras c est tres simple. Le HABTM c est les relations N-N.

TUTO HABTM

Et le lien de la doc cakephp: DOC HABTM CAKEPHP

En gros ca donnera ca: (Mais je te conseil de regarder la vidéo du tuto tu comprendras mieux :)

Table:
    matches (id, name, ...)
    users (id, userame, password, pseudo, ...)
    matches_users (id, match_id, user_id) -- (c est celle ci qui fera la liaison entre match et user)
Dans model User:
class User extends AppModel { 
    public $hasAndBelongsToMany = Match;
}
Dans model Match:
class Match extends AppModel { 
    public $hasAndBelongsToMany = User;
}

Avec cette facon de faire tu auras donc au final dans ta base par exmeple:

Table users(id, username):
1 - joueur1
2 - joueur2
3 - joueur3
4 - joueur4
Table matches (id, name):
1 - match1
2 - match2
3 - match3
Table matches_users(id, match_id, user_id):
1 - 1 - 1 ==> match1 joueur1
2 - 1 - 3 ==> match1 joueur3
3 - 2 - 2 ==> match2 joueur2 
4 - 2 - 4 ==> match2 joueur4
5 - 3 - 1 ==> match3 joueur1
6 - 3 - 4 ==> match3 joueur1
DexX
Auteur

Oui merci de l'aide, je comprend le principe mais il faut savoir, à ce moment là, que ma table matches_users contiendra 2 user_id (user_1 et user_2) car un match est composé de deux équipes, ici en l’occurrence, deux utilisateurs.

Non. Pourquoi veux ajouter user_1 et user_2 ?

Etant donnée que matches_users enregistre un match pour un joueur et ce meme match peut avoir un 2e ou 3e ou 4e joeuur

Table matches_users(id, match_id, user_id):
1 - 1 - 1 ==> le joueur1/equipe1 joue au match1
2 - 1 - 3 ==> le joueur3/equipe3 joue au match1
etc
regarde l exemple au dessus

apres dans matches_users tu peux ajouter d'autre champs par exemple:

Table matches_users (id, match_id, user_id, aller_retour,score, faute, etc...)

Comme ça tu gères chaque résultat pour chaque user/equipe a chaque match. Tu pourras avoir pour un match en particulier, le score de l équipe/user, si c ets un match aller ou retour, si il y a eu des fautes, cartons, etc... pour des stats

A moins que je n'ai absolument pas compris ce que tu cherches a faire.

DexX
Auteur

Si c'est parfait ça !

J'adapte mon code ce soir et je te tiens au juste si j'ai des difficultés ;)

DexX
Auteur

Mais petite question, du coup après, comment je fais avec mes modèles liés de cette manière pour générer mes matchs, remplir mes tables sachant que ma fonction qui me génère les matchs est :

public function generateMatchs($idChampionship) {
        $players = $this->query('SELECT User.id FROM user as User, participer as Participer WHERE User.id = Participer.user_id AND Participer.championship_id = '.$idChampionship.'');
        foreach ($players as $key => $value) {
            $joueurs] = $value'User']'id'];
        }
        foreach ($joueurs as $domicile) {
            foreach ($joueurs as $exterieur) {
                if ($domicile != $exterieur) {
                    $matchs] = $domicile.' - '.$exterieur;
                    $this->query('INSERT INTO `match` (championship_id, user_1, user_2) VALUES ('.$idChampionship.', '.$domicile.', '.$exterieur.')');
                }
            }
        }
    }

Pour le moment, sa sauvegarde les données de cette manière :

id, championship_id, user_1, user_2
1, 1, 1, 2