IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

ORM PHP Discussion :

Doctrine, schema.yml et contrainte d'unicité


Sujet :

ORM PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2009
    Messages
    100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2009
    Messages : 100
    Par défaut Doctrine, schema.yml et contrainte d'unicité
    Bonjour à tous,

    Alors pour une rapide présentation, je suis actuellement en train d'apprendre à utiliser symfony. Pour cela, j'ai rapidement lu et réaliser une partie du tutoriel 'Jobeet'. Je réalise maintenant un projet personelle.
    J'ai donc élaborer un modèle, j'ai ensuite générer automatiquement le schema.yml mais comme les clés étrangères n'étaient pas prise en compte, j'ai repris à la main ce fichier.
    Cependant, et c'est la que les ennuis commencent, j'ai un problême au niveau des contraintes de deux tables liées entre elles par une clé étrangère.

    Pour le SGBDR, j'utilise PostGreSql.

    Voici le code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    El_Candidats:
      connection: doctrine
      tableName: el_candidats
      columns:
        cotisant_id: { type: integer(4) , primary: true }
        poste_id: { type: integer(4), primary: true }
        description: { type: integer(4), notnull: true }
      relations:
        Co_Cotisants: { onDelete: CASCADE, onUpdate: CASCADE, local: cotisant_id, foreign: id, type: one, foreignType: many }
        El_Postes: { onDelete: CASCADE, onUpdate: CASCADE, local: poste_id, foreign: id, type: one, foreignType: many }
     
    El_Postes:
      connection: doctrine
      tableName: el_postes
      columns:
        id: { type: integer(4), primary: true }
        description: { type: string(), notnull: true }
     
    El_Votes:
      connection: doctrine
      tableName: el_votes
      columns:
        poste_id: { type: integer(4), primary: true }
        cotisant_id: { type: integer(4), primary: true }
        candidat_id: { type: integer(4), primary: true }
      relations:
        Co_Cotisants: { onDelete: CASCADE, onUpdate: CASCADE, local: cotisant_id, foreign: id, type: one, foreignType: many }
        El_Postes: { onDelete: CASCADE, onUpdate: CASCADE, local: poste_id, foreign: id, type: one, foreignType: many }
        El_Candidats: { onDelete: CASCADE, onUpdate: CASCADE, local: candidat_id, foreign: cotisant_id, type: one, foreignType: many }
    Et voici le SQL généré par la commande 'symfony doctrine:build --all':
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    CREATE TABLE el_candidats (poste_id SERIAL, cotisant_id INT, description INT NOT NULL, PRIMARY KEY(poste_id, cotisant_id));
    CREATE TABLE el_postes (id SERIAL, description TEXT NOT NULL, PRIMARY KEY(id));
    CREATE TABLE el_votes (poste_id SERIAL, cotisant_id SERIAL, candidat_id INT, PRIMARY KEY(poste_id, cotisant_id, candidat_id));
    ALTER TABLE el_candidats ADD CONSTRAINT el_candidats_poste_id_el_postes_id FOREIGN KEY (poste_id) REFERENCES el_postes(id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE;
    ALTER TABLE el_candidats ADD CONSTRAINT el_candidats_cotisant_id_el_votes_candidat_id FOREIGN KEY (cotisant_id) REFERENCES el_votes(candidat_id) NOT DEFERRABLE INITIALLY IMMEDIATE;
    ALTER TABLE el_candidats ADD CONSTRAINT el_candidats_cotisant_id_co_cotisants_id FOREIGN KEY (cotisant_id) REFERENCES co_cotisants(id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE;
    ALTER TABLE el_votes ADD CONSTRAINT el_votes_poste_id_el_postes_id FOREIGN KEY (poste_id) REFERENCES el_postes(id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE;
    ALTER TABLE el_votes ADD CONSTRAINT el_votes_cotisant_id_co_cotisants_id FOREIGN KEY (cotisant_id) REFERENCES co_cotisants(id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE;
    ALTER TABLE el_votes ADD CONSTRAINT el_votes_candidat_id_el_candidats_cotisant_id FOREIGN KEY (candidat_id) REFERENCES el_candidats(cotisant_id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE;
    J'ai alors plusieurs questions :
    1. Pourquoi la commande SQL suivante est généré
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      ALTER TABLE el_candidats ADD CONSTRAINT el_candidats_cotisant_id_el_votes_candidat_id FOREIGN KEY (cotisant_id) REFERENCES el_votes(candidat_id) NOT DEFERRABLE INITIALLY IMMEDIATE;
      alors que nul part dans mon schema.yml, il y a une contrainte de clé étrangère de el_candidats vers el_votes ...
    2. Je voulais savoir si il était possible que les deux colonnes concerné soit de type différent (INT et SERIAL dans mon cas)


    De plus lorsque j'essaye d'éxecuter ce code, j'obtient l'erreur suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SQLSTATE[42830]: Invalid foreign key: 7 ERREUR:  il n'existe aucune contrainte unique correspondant aux clés données pour la table « el_votes » référencée.
    Failing Query: "ALTER TABLE el_candidats ADD CONSTRAINT el_candidats_cotisant_id_el_votes_candidat_id FOREIGN KEY (cotisant_id) REFERENCES el_votes(candidat_id) NOT DEFERRABLE INITIALLY IMMEDIATE".
    Si vous voulez me poser des questions supplémentaires, n'hésitez pas.
    Inarius

  2. #2
    Expert confirmé
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Par défaut
    Je ne connais pas postgre si ce n'est de nom.

    Par contre, je connait relativement bien doctrine, et je pense que c'est là que ce trouve ta solution.

    Par contre, il semble manquer une table dans ton schema : Co_Cotisants


    Question 3
    Ton schema n'est pas réellement simple, doctrine 1.2 n'aime pas vraiment les clefs multiples. De plus (pas simple avec l'absence supposée de la table Co_Cotisants) mais j'ai l'impression qu'une des liaisons entre vote et poste ou entre candidat et poste est en trop, suivant ce que tu veux faire.

    L'erreur pourait être là

    Question 2
    non (ça c'est des réponses simple) même type.

    Question 1
    Je propose de régler d'abord le schéma pour qu'il s'implémente correctement, il est possible que cette contrainte soit une conséquence de la question 3.


    Pourrais-tu mettre le code de la table qui semble manquante.

    Dans les conseils supplémentaires :
    • Évite les préfixe sur les nom des objets (le nom de la table peut-être différent du nom de l'objet.
    • Évite de mettre les nom des tables au pluriels et le nom des objets. Le schema va généré plus que les tables, il va générer le modèle, les form et les filter. Avec ton schéma un objet vote apparaîtra sous la forme de ElVotes ce qui ne laisse pas de place à une collection des votes qui devrait alors s'appeler ElVotess ce qui est peu lisible.

  3. #3
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2009
    Messages
    100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2009
    Messages : 100
    Par défaut
    Pour ce qui est de la table manquante, c'est juste que je ne l'ai pas poster mais elle existe bien et est bien dans le schéma (Pour clarifier le tout, j'ai mis une représentation du modèle en pièce jointe)

    Ensuite pour le suffixe, je désire le garder car il y a environ 18 tables, nombre qui est ammené à augmenter. Et chaque table est plus ou moins lié à d'autres tables, mais comme elles ne sont pas toutes dans la même catégorie (sp_photos, ga_photos, ) c'est beaucoup plus simple à gérer. De même pour le nom des objets

    Ensuite, je ne vois pas vraiment ou est la liason en trop :s J'espère que la modélisation que j'ai mis en pièce jointe pourra t'aider à m'aider

    Et enfin pour les 's' à la fin des objets, je m'en vais les retirer de suite

  4. #4
    Expert confirmé
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Par défaut
    Soit pour les préfixes, c'est une bonne méthode de travail, je suis sans doutes plus confus.

    On va juste discuter, pour commencer sur le schéma, et sur la partie qui t'intéresse avec le préfixe EL.

    Si je comprends bien.

    On a des cotisants qui peuvent ce porter candidat à un poste.
    On a des cotisants qui peuvent voter pour un candidat à un poste

    Il me semblerait logique qu'un cotisants ne puisse voter que pour une candidature (un cotisant pour un poste). Hors dans ton schéma, un cotisant peut lui même choisir le candidat (a condition qu'il se soit présenté à un poste) et le poste qui peut être différent de celui auquel le candidat prétend du fait de la liaison entre la table poste et la table vote. C'est là que je vois le liens de trop. Il me semblerait plus logique que la clef (poste) de vote soit en liaison avec la clef (poste) de candidat.

    De plus il semblerait manquer un attribut à la table vote permettant de préciser le vote.

    Je pense qu'il serait plus simple de créer une clef unique sur la table candidature pour gérer la liaison, Doctrine n'aime pas les clefs composées.

    De plus, en passant très vite sur ton schéma je suis tombé sur la table sp_sports, c'est le champs Belfort qui a attiré mon regard, on est presque voisin. Dans cette table, il semblerait qu'il y ait, en dur des lieux, ce qui n'est pas conforme aux formes normal et rendrait très compliqué tout ajout d'un nouveau lieu.

    Autre choses, tu as deux tables photos identiques... m'est avis qu'elle auraient intérêt à être regroupées avec un code qui indiquerait le rattachement de la photo. Un seul système de gestion des téléchargement et une consultations centralisée possible.

    C'est les principaux points du schéma qui ont attiré mon œil, mais je pense qu'il y a d'autres choses qui pourrait être discutées, mais ceci n'était pas l'objectif du message.

    Réfléchi à ces liens dans la partie élection, il doit y avoir quelque chose qui cloche.

  5. #5
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2009
    Messages
    100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2009
    Messages : 100
    Par défaut
    Alors pour répondre à ta question de nom des villes dans la table sport, en fait il s'agit du future site du Bureau de Sports de l'UTBM ^^ Donc comme les sports se déroulent soit à Sevenans soit à Belfort soit à MontBélliard soit deux ou même les trois, et que l'UTBM ne s'implémente dans une autre ville, on a le temps

    Ensuite pour les tables 'sp_photos' et 'ga_photos', j'avais déjà penser à centraliser les photos dans une seul et même table cependant je préfère ne pas mettre de table centralisé pour toutes les photos pour permettre de pouvoir supprimé des parties de code facilement sans surchargé la bdd ni rien, donc je trouve personnelement que ce sera plus rangé comme ca

    Et finalement pour les votes, j'ai complétement simplifier le tout

    Donc voila ce que ca devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    El_Candidat:
      connection: doctrine
      tableName: el_candidats
      columns:
        cotisant_id: { type: integer(4) , primary: true }
        poste_id: { type: integer(4), primary: true }
        description: { type: integer(4), notnull: true }
        nb_vote: { type: integer(4), notnull: true }
      relations:
        Co_Cotisant: { onDelete: CASCADE, onUpdate: CASCADE, local: cotisant_id, foreign: id, type: one, foreignType: many }
        El_Poste: { onDelete: CASCADE, onUpdate: CASCADE, local: poste_id, foreign: id, type: one, foreignType: many }
     
    El_Poste:
      connection: doctrine
      tableName: el_postes
      columns:
        id: { type: integer(4), primary: true, autoincrement: true }
        description: { type: string(), notnull: true }
    Donc maintenant les votes sont complétements anonymes (ce qui n'est pas plus mal ) et ensuite ca marche

    Mais merci beaucoup de ton aide et dsl mais j'ai pas tout compris a ce que tu as dis
    Il me semblerait logique qu'un cotisants ne puisse voter que pour une candidature (un cotisant pour un poste). Hors dans ton schéma, un cotisant peut lui même choisir le candidat (a condition qu'il se soit présenté à un poste) et le poste qui peut être différent de celui auquel le candidat prétend du fait de la liaison entre la table poste et la table vote. C'est là que je vois le liens de trop. Il me semblerait plus logique que la clef (poste) de vote soit en liaison avec la clef (poste) de candidat.

    De plus il semblerait manquer un attribut à la table vote permettant de préciser le vote.

  6. #6
    Expert confirmé
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Par défaut
    Citation Envoyé par Inarius Voir le message
    Alors pour répondre à ta question de nom des villes dans la table sport, en fait il s'agit du future site du Bureau de Sports de l'UTBM ^^ Donc comme les sports se déroulent soit à Sevenans soit à Belfort soit à MontBélliard soit deux ou même les trois, et que l'UTBM ne s'implémente dans une autre ville, on a le temps
    C'est probable effectivement que cela ne soit jamais le cas, mais, niveau analyse ce n'est pas "satisfaisant", même étant sur qu'il n'y a aucune chance que... Suivant la loi de l'emmerdement maximal, ça va arriver, soit une autre salle, soit dans un quartier qui devra être nommé,...

    Citation Envoyé par Inarius Voir le message
    Ensuite pour les tables 'sp_photos' et 'ga_photos', j'avais déjà penser à centraliser les photos dans une seul et même table cependant je préfère ne pas mettre de table centralisé pour toutes les photos pour permettre de pouvoir supprimé des parties de code facilement sans surchargé la bdd ni rien, donc je trouve personnelement que ce sera plus rangé comme ca
    C'est une manière de voir les choses. Mais je continue de penser que si le système est bien conçu, tu aurais juste un module "photo" en plus. Soit plus d'indépendance et surtout pas de redondance du code. Avec ta solution, si tu veux changer un traitement sur les photos, tu vas être bon pour vérifier les deux codes... Bien conçu, tu n'auras ni surcharge de la BD, ni duplication de code. Mais c'est toi qui code.

    Citation Envoyé par Inarius Voir le message
    Mais merci beaucoup de ton aide et dsl mais j'ai pas tout compris a ce que tu as dis
    Hélas, parfois je ne suis pas clair, et un bon dessins aurait été meilleur, mais en dessin aussi, je ne suis pas fort.

    Tes modifications ont supprimé toutes mes remarques.

    J'en rajoute une sur tes modification. L'avantage est que tu ne sais pas qui a voter pour qui et que ce n'est plus traçable, ce qui correspond à un vote secret, et est un mieux. D'un autre côté, tu ne sais pas qui a voté, et que tu risques de saisir deux fois un même vote.

    Et une dernière, où gères-tu la composition du bureau, une fois les élections terminées ?

  7. #7
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2009
    Messages
    100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2009
    Messages : 100
    Par défaut
    Donc oui c'est bel et bien ma première appli

    Mais c'est vrai que comme, par le passé, je n'utilisait pas de framework, j'ai pris l'habitude de tout faire moi même. Donc c'est vrai que c'est assez lourd par rapport à ce que ca devrait être.

    Ensuite, oui Doctrine Hydrate déjà pas mal le résultat, mais je trouve le résultat assez illisible ; Par la je veut dire que par exemple pour les salles, il faut faire une autre requête d'où une autre table.

    Et, pour moi, dans le pattern MVC, dans le V, il n'y a que de la logique de présentation, les données sont toutes prêtes, pas besoin de se dire, ah oui, il y a a salle_id = X, donc faut que j'aille chercher dans le résultat de la table salle l'id X ,...
    Dans le C, c'est juste une liaison du V et du M. Donc juste $this->variable = Doctrine_Core::getTable('XXX')->getVariableAvecComplementTouteLesRelations ...
    Et donc finalement le M, c'est la que le gros du traval est réalisé. (je te rassure, le gros du code est dans le modèle ). Donc la ce que j'ai fait:

    Dans le Controleur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public function executeShow(sfWebRequest $request) {
        $sport = Doctrine_Core::getTable('spSport')->getCompleteSport( $request->getParameter('id') );
     
        $this->forward404Unless($sport);
     
        $this->sport = $sport;
    }
    Dans le Modèle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
     
    /**
     * Fonction permettant d'obtenir toutes les informations à propos d'un sport. L'array retourner est de la forme :
     *   id : int
     *   nom : string
     *   description : string
     *   matos: string
     *   actif: boolean
     *   horaires:
     *     id: int
     *     salle:
     *       id: int
     *       nom: string
     *       ville: string
     *       adresse: string
     *     jour: string
     *     heure:
     *       debut: timestamp
     *       fin: timestamp
     *   participants:
     *     id: int
     *     nom: string
     *     prenom: string
     *     photo_id: int
     *     statut: string
     *   photos:
     *     id: int
     * 
     * @param int $id Id du sport à récupérer
     * @return array Contient toutes les information à propos d'un sport ( horaires, participants, photos ) cf ci dessus pour la structure
     */
    public function getCompleteSport($id) {
        if ( empty($id) || $id === null )
            return false;
     
        // On récupère la table sport avec les tables de liaisons qui correspondent aux participants, aux photos et aux horaires
        $q = new Doctrine_RawSql();
        $sport_infos = $q->select('
                    {s.nom},
                    {s.description},
                    {s.matos},
                    {s.actif},
                    {h.salle_id},
                    {h.jour},
                    {h.heure_debut},
                    {h.heure_fin},
                    {pa.cotisant_type_id}')
                ->from('
                    sp_sports s
                    LEFT JOIN sp_participants pa ON s.id = pa.sport_id
                    LEFT JOIN sp_photos po ON s.id = po.sport_id
                    LEFT JOIN sp_horaires h ON s.id = h.sport_id')
                ->where('s.id = ?', $id)
                ->addComponent('s', 'spSport s')
                ->addComponent('pa', 's.sp_participants pa')
                ->addComponent('po', 's.sp_photos po')
                ->addComponent('h', 's.sp_horaires h')
                ->execute(array(), Doctrine::HYDRATE_ARRAY);
     
        if(empty($sport_infos))
            return false;
     
        // On récupère toutes les informations nécessaires sur les participants : nom, prenom, statut dans le sport (responsable, co responsable , ...), etc...
        if (!empty($sport_infos[0]['sp_participants'])) {
            // On fait la liste des participants et des statuts pour aller récupérer leurs infos
            foreach ( $sport_infos[0]['sp_participants'] as $participant ) {
                $participants_id[] = $participant['cotisant_id'];
                $participants_statuts[] = $participant['cotisant_type_id'];
            }
     
            // Récupération des infos personnelles
            $q = new Doctrine_RawSql();
            $cotisants_infos = $q->select('
                        {c.nom},
                        {c.prenom},
                        {c.photo_id}')
                    ->from('co_cotisants c')
                    ->where('c.id IN (' . implode( ',', $participants_id ) . ')')
                    ->addComponent('c', 'coCotisant c')
                    ->execute(array(), Doctrine::HYDRATE_ARRAY);
     
            // Récupération des infos sur le statut
            $q = new Doctrine_RawSql();
            $statuts_infos = $q->select('{st.description}')
                    ->from('sp_participants_types st')
                    ->where("st.id IN (" . implode(',', $participants_statuts) . ')')
                    ->addComponent('st', 'spParticipantType st')
                    ->execute(array(), Doctrine::HYDRATE_ARRAY);
            ;
        }
     
        // On récupère maintenant toutes les infos sur les horaires et donc les salles: nom, lieu, adresse, heure, jour,...
        if (!empty($sport_infos[0]['sp_horaires'])) {
            // On fait la la liste de toutes les salles prise par ce sport, pour ensuite récupérer leurs infos dans la table sp_salles
            foreach ( $sport_infos[0]['sp_horaires'] as $horaire )
                $horaires_salle_id[] = $horaire['salle_id'];
     
            $q = new Doctrine_RawSql();
            $salles_infos = $q->select('
                        {sa.adresse},
                        {sa.nom},
                        {sa.ville}')
                    ->from('sp_salles sa')
                    ->where('sa.id IN (' . implode( ',', $horaires_salle_id ) . ')' )
                    ->addComponent('sa', 'spSalle sa')
                    ->execute(array(), Doctrine::HYDRATE_ARRAY);
        }
     
        // On commence donc par remettre en forme les infos sur les salles pour condenser le tout
        if (isset($salles_infos)) {
            // On condense les salle
            foreach ( $salles_infos as $salle )
                $salles["{$salle['id']}"] = array(
                        'id' => $salle['id'],
                        'nom' => $salle['nom'],
                        'ville' => $salle['ville'],
                        'adresse' => $salle['adresse']
                );
     
            // On condense les horaires en y incluant les salles correspondantes
            foreach ( $sport_infos[0]['sp_horaires'] as $horaire )
                $horaires["{$horaire['id']}"] = array(
                        'id' => $horaire['id'],
                        'salle' => $salles[$horaire['salle_id']],
                        'jour' => $horaire['jour'],
                        'heure' => array('debut' => date( 'H:i', strtotime( $horaire['heure_debut'] ) ), 'fin' => date( 'H:i', strtotime( $horaire['heure_fin'] ) ) )
                );
        }
     
        // On met maintenant en forme les participants ( participant = cotisant + statut )
        if ( isset($cotisants_infos) && isset($statuts_infos) ) {
            // On met en forme les cotisants
            foreach ( $cotisants_infos as $cotisant )
                $cotisants["{$cotisant['id']}"] = array(
                        'nom' => $cotisant['nom'],
                        'prenom' => $cotisant['prenom'],
                        'photo_id' => $cotisant['photo_id']
                );
     
            // On met en forme les statuts
            foreach ( $statuts_infos as $statut )
                $statuts["{$statut['id']}"] = array('description' => $statut['description']);
     
            // On condense le tout en incluant les statut et les cotisants au sein d'un même tableau pour donnée un tableau de participants
            foreach ( $sport_infos[0]['sp_participants'] as $participant )
                $participants["{$participant['cotisant_id']}"] = array(
                        'id' => $participant['cotisant_id'],
                        'nom' => $cotisants["{$participant['cotisant_id']}"]['nom'],
                        'prenom' => $cotisants["{$participant['cotisant_id']}"]['prenom'],
                        'photo_id' => $cotisants["{$participant['cotisant_id']}"]['photo_id'],
                        'statut' => $statuts["{$participant['cotisant_type_id']}"]['description']
                );
        }
     
        // On met en forme les photos
        if ( !empty( $sport_infos[0]['sp_photos'] ) )
            foreach ( $sport_infos[0]['sp_photos'] as $photo)
                $photos[] = $photo['photo_id'];
     
        // Phase final: on condense les infos sur le sport, sur les participants, les horaires et les photos au sein d'un même tableau.
        $sport = array(
                'nom' => $sport_infos[0]['nom'],
                'description' => $sport_infos[0]['description'],
                'matos' => $sport_infos[0]['matos'],
                'actif' => $sport_infos[0]['actif'],
                'horaires' => isset( $horaires ) ? $horaires : false,
                'participants' => isset( $participants ) ? $participants : false,
                'photos' => isset( $photos ) ? $photos : false
        );
     
        // On verifie qu'il n'y est pas d'informations manquantes pour eviter les erreur d'affichage
        return ( empty($sport['nom']) || empty($sport['description']) || empty($sport['matos']) ) ? false : $sport;
    }
    Dans la Vue
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
     
    <style type="text/css">
        .table,.table td,.table tr{border:1px solid black;border-collapse:collapse;padding:5px;margin: 4px 0}
    </style>
     
    <?php if ( $sport['actif'] === false ) : ?>
    <h3>Ce sport est inactif ce semestre</h3><br/><br/>
    <?php endif ?>
     
    <table class="table">
        <tr>
            <td>Nom</td>
            <td><?php echo $sport['nom'] ?></td>
        </tr>
        <tr>
            <td>Presentation</td>
            <td><?php echo $sport['description'] ?></td>
        </tr>
        <tr>
            <td>Matériel mis à disposition</td>
            <td><?php echo $sport['matos'] ?></td>
        </tr>
        <tr>
            <td>Horaires</td>
            <td>
                <?php if ($sport['horaires'] !== false ) : ?>
                <table class="table">
                    <tr>
                        <td>Horaires</td>
                        <td>Salle et adresse</td>
                        <td>Ville</td>
                    </tr>
                        <?php foreach ( $sport['horaires'] as $horaire ) : ?>
                    <tr>
                        <td><?php echo "{$horaire['jour']}, de {$horaire['heure']['debut']} à {$horaire['heure']['fin']}" ?></td>
                        <td><?php echo $horaire['salle']['nom'] ?><br/><?php echo $horaire['salle']['adresse'] ?></td>
                        <td><?php echo $horaire['salle']['ville'] ?></td>
                    </tr>
                        <?php endforeach ?>
                </table>
                <?php else : ?>
                Aucun horaire pour ce sport
                <?php endif ?>
            </td>
        </tr>
        <tr>
            <td>Nombre de photos</td>
            <td><?php echo count( $sport['photos'] ) ?></td>
        </tr>
        <tr>
            <td>Nombre de participants</td>
            <td><?php echo count( $sport['participants'] ) ?></td>
        </tr>
    </table>
    <br/>
    <h2>Participants</h2>
    <br/>
    <?php if ( $sport['participants'] !== false ) : ?>
        <?php foreach ( $sport['participants'] as $participant ) : ?>
    <table class="table">
        <tr>
            <td colspan="2"><?php echo "{$participant['nom']} {$participant['prenom']}" ?></td>
        </tr>
        <tr>
            <td><?php echo $participant['statut'] ?></td>
            <td><?php echo $participant['photo_id'] ?></td>
        </tr>
    </table>
        <?php endforeach ?>
    <?php else : ?>
    Aucun participant à ce sport
    <?php endif ?>
    <br/>
    <br/>
    <h2>Photos</h2>
    <br/>
    <?php if ( $sport['photos'] !== false ) : ?>
        <?php foreach ( $sport['photos'] as $photo ) : ?>
            <?php echo $photo ?>&nbsp;&nbsp;&nbsp;
        <?php endforeach ?>
    <?php else : ?>
    Aucune photo pour ce sport
    <?php endif ?>

    J'espère que le code est plus cair une fois commenter ^^
    Donc en fait faut bien comprendre que ca se passe en deux temps:
    - le premier: on récupère toutes les infos dans la bdd
    - le deuxième: on reforme un tableau propre et complet que l'on va renvoyer

    Ensuite, pour la mise en page, la j'ai juste mis dans un tableau pour voir si ca marche. Mais il y a quelqu'un d'autre bien meilleur en graphisme que moi qui va passer derrière pour mettre tout ca en forme

    Et pour finir, c'est surement le cas que je commence à construire la tour par le 20 ème étage mais tu sais jveux faire Info, faut pas me demander de question sur du Génie civile Nan mais c'est vrai mais, comme dit, j'ai déjà fait quelques trucs avant, mais comme c'est la première fois que j'utilise un framework de cette envergure (ou même un framework tout court) je pense que je m'enflamme un peu

  8. #8
    Expert confirmé
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Par défaut
    Pour le génie civil, s'était juste une vue de l'esprit, laissons tomber (du vingtième !)

    Pour le V on est (presque) d'accord. Il y a un peu de code pour les foreach, mais c'est tous.

    Pense malgré tous à la possibilité d'afficher des listes (tables) de cotisant à plusieurs endroits et aux partial qui permettent d'éviter la duplication du code.


    Pour le C, il est bon.

    Pour le M..... y a encore du boulot.

    Dans le cadre d'un enregistrement, il n'y a pas vraiment intérêt à faire de l'hydratation par array. Le gain d'accès est minime.

    Ta requête pourrait donner quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    $q = Doctrine_Query::create()
         ->from('sp_sport s')
         ->leftJoin('co_cotisant c')
         ->leftJoin('sp_horraire h')
         ->leftJoin('ph_photo p')
         ->where('s.id = ?', $Id);
     
    returne $q->fechtOne();
    Je ne suis pas replongé dans le schema, mais on devrait ne pas être loin de ça.

    tu récupère un 'objet sport dans ton contrôleurs (logique vu le where sur id) dans $this->sport = ...

    Puis dans ton template, pour le sport tu vas avoir
    <?php echo $sport->getNom() ?>

    Et pour la liste des cotisants
    <?php foreach $sport->getCotisants() as $cotisant : ?>
    <?php echo $cotisant->getNom() . ' ' . $cotisant->getPrenom() ?>
    <?php endforeach ?>

    Ceci nécessite que les relations dans le modèles soient parfaitement écrites.

    Et le code me semble un peu plus léger.

  9. #9
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2009
    Messages
    100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2009
    Messages : 100
    Par défaut
    Salut,

    Apres une petite pause (examens obligent ^^), j'ai repris mon petit bonhomme de chemin. Et j'ai décider de t'écouter

    J'ai donc repris completement mon schema.yml. Et j'ai aussi appris à utiliser les leftJoin des Doctrine_Query.

    Donc c'est vrai que c'est quand même plus facile et rapide à mettre en place mais qu'est ce que c'est lent Avant ça mettais environ 120 mS, la ça en met environ 700 mS ( avec APC ... ) ......... Mais bon la faciliter l'emporte

    Donc voici à quoi j'arrive (j'ai repris le même exemple que 2 ou 3 post avant, pour la comparaison) :
    Modele
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    public function getCompleteActiviteById($id) {
        if ( empty($id) || $id === null )
            return false;
     
        return Doctrine_Query::create()
                ->from('gaActivite g')
                ->leftJoin('g.gaParticipants pa')
                ->leftJoin('g.gaPhotos po')
                ->leftJoin('pa.sfGuardUserProfile c')
                ->where('g.actif AND g.id = ?', $id)
                ->fetchOne();
    }
    Controller
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public function executeShow(sfWebRequest $request) {
        $activite = Doctrine_Core::getTable('gaActivite')->getCompleteActiviteById($request->getParameter('id'));
     
        $this->forward404Unless($activite);
     
        $this->activite = $activite;
    }
    View
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
     
    <style type="text/css">
        .table,.table td,.table tr{border:1px solid black;border-collapse:collapse;padding:5px;margin: 4px 0}
    </style>
     
    <table>
        <tr>
            <td>Nom</td>
            <td><?php echo $activite->getNom() ?></td>
        </tr>
        <tr>
            <td>Presentation</td>
            <td><?php echo $activite->getPresentation() ?></td>
        </tr>
        <tr>
            <td>Date de commencement</td>
            <td><?php echo $activite->getDateDebut() ?></td>
        </tr>
        <tr>
            <td>Date de fin</td>
            <td><?php echo $activite->getDateFin() ?></td>
        </tr>
        <tr>
            <td>Nombre de participants</td>
            <td><?php echo $activite->getGaParticipants()->count() ?></td>
        </tr>
        <tr>
            <td>Nombre de photos</td>
            <td><?php echo $activite->getGaPhotos()->count() ?></td>
        </tr>
    </table><br/>
     
     
    <h2>Participants</h2><br/>
    <?php if ( $activite->getGaParticipants()->count() > 0 ) : ?>
        <?php foreach ( $activite->getGaParticipants() as $participant ) : ?>
    <table class="table">
        <tr>
            <td colspan="2"><?php echo $participant->getSfGuardUserProfile()->getNom() . ' ' . $participant->getSfGuardUserProfile()->getPrenom() ?></td>
        </tr>
        <tr>
            <td>email : <?php echo $participant->getSfGuardUserProfile()->getEmail() ?></td>
            <td>id photo : <?php echo $participant->getSfGuardUserProfile()->getPhotoId() ?></td>
        </tr>
    </table>
        <?php endforeach ?>
    <?php else : ?>
    Aucun participant à cette grande activitée
    <?php endif ?><br/><br/>
     
     
    <h2>Photos</h2><br/>
    <?php if ( $activite->getGaPhotos()->count() > 0 ) : ?>
        <?php foreach ( $activite->getGaPhotos() as $photo ) : ?>
            <?php echo $photo->getPhotoId() . "\t" ?>
        <?php endforeach ?>
    <?php else : ?>
    Aucun photo de cette grande activitée
    <?php endif ?>
    Et c'est vrai que c'est quand même plus simple à implementer xD

    J'ai donc plus qu'à modifier le reste et c'est partie ^^

  10. #10
    Expert confirmé
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Par défaut
    Et je te fais gagner une ligne de code, soit 2 millième en poins, tu vas passer de 700 à 698

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    public function executeShow(sfWebRequest $request) {
        $this->activite = Doctrine_Core::getTable('gaActivite')->getCompleteActiviteById($request->getParameter('id'));
     
        $this->forward404Unless($this->activite);
    }
    Pour tes mesures, essaye la deuxième exécution en mode normal (pas avec frontend_dev.php), puis sur un autre enregistrement.

    Il reste la possibilité, si les données sont souvent consultées et peu modifiées, d'utiliser le cache de symfony, qui peut, là, accélérer notablement les requêtes, sans ajouter des contraintes de développement énormes.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Doctrine] Relation entre deux tables dans schema.yml sans contrainte
    Par ninorotto dans le forum ORM
    Réponses: 8
    Dernier message: 24/08/2011, 10h26
  2. [doctrine]problème avec syntaxe du schema.yml
    Par flora806 dans le forum ORM
    Réponses: 3
    Dernier message: 15/03/2011, 10h19
  3. schema.yml pour relation n-n Doctrine
    Par psgman113 dans le forum ORM
    Réponses: 3
    Dernier message: 22/03/2010, 19h59
  4. [Doctrine] 2 schema.yml
    Par zoukkev dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 15/04/2009, 11h54

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo