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 :

Eviter les doublons sur le nom par exemple [Doctrine]


Sujet :

ORM PHP

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Février 2011
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2011
    Messages : 23
    Points : 15
    Points
    15
    Par défaut Eviter les doublons sur le nom par exemple
    Bonjour,
    Je voudrais mettre en place un petit système de tags.
    Pour cela, j'ai deux tables: Tags et tags_lnk
    Tags reprend juste le tag (nom et compteur) et l'autre table fait le lien avec les éléments à tagger.

    Je voudrais donc être certain qu'un tag ne se retrouve qu'une fois dans la table Tags. Je voudrais donc savoir comment être certain qu'il n'y a pas déjà un tag.

    Je pensais faire une fonction exists dans la classe Tags qui retourne 0 s'il n'existe pas, -1 s'il y en a plusieurs ou l'id du tag.

    Je dois faire comme ça ou il y a des solutions plus "propres" ?

    Merci d'avance.

    Gp2mv3

  2. #2
    Expert éminent
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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
    Points : 8 486
    Points
    8 486
    Par défaut
    Doctrine utilise des extensions nommée behavior.

    L'une d'elle permet de gérer des slug, c'est le nom du comportement que tu appels tag.

    Tu as la documentation ici.

    N'hésite pas à poster ton schéma (shema.yml) ici si tu veux un avis pour un premier schéma. (et s'il n'est pas trop grand )
    Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).

    • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
    • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
    • Une discussion est terminée ? Alors le bouton est votre ami !

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Février 2011
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2011
    Messages : 23
    Points : 15
    Points
    15
    Par défaut
    J'ai regardé les slug et en faite, je les utilise déjà pour les url.
    Mais par contre, c'est pas vraiment ça que je veux faire.
    Je voudrais quelque chose permettant par exemple de trier tous les éléments avec le tag rouge et le tag bleu.

    Pour permettre des catégorisations des éléments. Un peu comme le font les moteurs de recherche mais en bien moins poussé biensur.

  4. #4
    Expert éminent
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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
    Points : 8 486
    Points
    8 486
    Par défaut
    Je ne suis pas sur d'être sur ton chemin de pensée, mais tu as un autre behavior qui permet de taguer des tables. Il s'installe avec un plugin symfony qui permet de générer les écrans liés.

    Si non, ton idée me semble réalisabe, quoiqu'une méthode qui retourne des choses différentes suivant les cas ne me semble pas optimal.

    Retourner un nul si pas de tag et un array des tag ou encore mieux un doctrine_collection des tag me semblerait mieux. Tu peux lui adjoindre une méthode count et ou exist.
    Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).

    • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
    • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
    • Une discussion est terminée ? Alors le bouton est votre ami !

  5. #5
    Membre éprouvé Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Points : 933
    Points
    933
    Par défaut
    Citation Envoyé par Gp2mv3 Voir le message
    Je pensais faire une fonction exists dans la classe Tags qui retourne 0 s'il n'existe pas, -1 s'il y en a plusieurs ou l'id du tag.
    En complément de l'observation de Michel, si un tag est unique, il me semble que la réponse "-1 s'il y en a plusieurs" signale un problème de cohérence.

    Faire une fonction exists() qui teste l'existence en base et renvoie true s'il existe me parait bien. Note que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TagTable::createInstance()->findByName('tag-a-tester')->count()
    fait aussi l'affaire (en supposant que la colonne s'appelle 'name')

    Dans tous les cas, déclarer une contrainte UNIQUE en base de données sur la colonne ad hoc de la table tag me semble incontournable.
    Et, bien sûr, ajouter cette contrainte dans le schema.yml de ton modèle.

    Enfin, pour gérer cette contrainte au niveau du formulaire, combiner un sfValidatorDoctrineUnique() avec les validateurs utilisés pour le champ en question du formulaire peut être une application commode du principe 'mieux vaut prévenir que guérir'.

  6. #6
    Expert éminent
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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
    Points : 8 486
    Points
    8 486
    Par défaut
    Je plussoies
    Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).

    • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
    • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
    • Une discussion est terminée ? Alors le bouton est votre ami !

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Février 2011
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2011
    Messages : 23
    Points : 15
    Points
    15
    Par défaut
    Pour le unique, j'ai une grosse erreur à la génération des tables.
    Voici l'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SQLSTATE[42000]: Syntax error or access violation: 1170 BLOB/TEXT column 'name' used in key specification without a key length. Failing Query: "CREATE TABLE tags (id BIGINT AUTO_INCREMENT, name TEXT NOT NULL UNIQUE, counter BIGINT DEFAULT 0, PRIMARY KEY(id)) ENGINE = INNODB". Failing Query: CREATE TABLE tags (id BIGINT AUTO_INCREMENT, name TEXT NOT NULL UNIQUE, counter BIGINT DEFAULT 0, PRIMARY KEY(id)) ENGINE = INNODB
    Et le schema.yml:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Tag:
      columns:
        name:
          type: string
          notnull: true
          unique: true
        counter: { type: integer, notnull: false, default: 0 }
    EDIT: J'ai résolu l'erreur sans trop de problème, j'avais pas compris qu'il voulait une taille pour le string.

    Par contre, ma fonction exists je dois la mettre dans quel fichier ? Tags.class.php ou TagsTable.class.php ?
    Si vous savez m'éclaircir sur la différence entre les deux ça m'intéresse aussi.

  8. #8
    Membre éprouvé Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Points : 933
    Points
    933
    Par défaut
    C'est une question presque philosophique .

    Pour faire bref et simple, je dirai que ça n'a pas beaucoup d'importance tant que la présentation reste claire.

    Le principe :
    1 - Tag est un objet instancié, TagTable est une collection d'objets de type Tag.
    2 - Tu cherches à savoir si un objet précis existe. S'il n'existe pas, tu ne peux pas l'instancier.

    Tu as donc deux approche possibles :

    - l'approche holiste : c'est la TagTable qui prime :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public static function TagTable::nameExists($name) {
      return self::createInstance()->findByName('tag-a-tester')->count() > 0;
    }
     
    // appel dans ton code : 
    if(TagTable::nameExists('tagada') {
       ...
    }
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public function TagTable::nameExists($name) {
      return $this->findByName('tag-a-tester')->count() > 0;
    }
     
    // appel dans ton code : 
    if(TagTable::createInstance()->nameExists('tagada') {
       ...
    }
    - l'approche individualiste : c'est le Tag qui prime :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public static function Tag::nameExists($name) {
      return TagTable::createInstance()->findByName('tag-a-tester')->count() > 0;
    }
     
    // appel dans ton code : 
    if(Tag::nameExists('tagada') {
       ...
    }
    Comme dans tous les cas il faut passer par TagTable, je préfère l'approche holiste.

    Comme il est en général inutile d'avoir une instance de la classe TagTable car tout ce qui nous intéresse ce sont les opérations sur la table et non la table elle-même, je préfère la première solution.

    Mais je n'irais pas jusqu'à déclencher une guerre de religion contre quelqu'un qui coderait l'une des autres approches. Tant que ça reste cohérent avec le reste de son code.

  9. #9
    Membre éprouvé Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Points : 933
    Points
    933
    Par défaut
    column 'name' used in key specification without a key length.
    Tout est dans le message d'erreur. Le type TEXT (taille indéfinie) ne peut pas être utilisé dans une clé - essentiellement pour des raisons de performances du moteur de base de données.

    Mais tu n'as probablement pas besoin d'un champ 'name' de taille indéfinie. A toi de voir quelle est la taille maximale désirable, en général un varchar(xx) fait l'affaire. Et dans le schéma par exemple pour un varchar(45):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Tag:
      columns:
        name:
          type: string(45) 
          notnull: true
          unique: true
    ...

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Février 2011
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2011
    Messages : 23
    Points : 15
    Points
    15
    Par défaut
    Merci beaucoup pour vos éclaircissements.
    Je vais donc faire comme tu l'as proposé avec le unique et le exists.

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

Discussions similaires

  1. Eviter les doublons sur un champ SQL Serveur 2005
    Par crashyear dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 05/12/2006, 08h02
  2. [Débutant][XSLT]Eviter les doublons
    Par leminipouce dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 21/10/2005, 11h34
  3. hash et Tie , eviter les doublons
    Par bluecurve dans le forum Langage
    Réponses: 5
    Dernier message: 12/10/2005, 16h39
  4. Eviter les doublons
    Par cyrill.gremaud dans le forum ASP
    Réponses: 5
    Dernier message: 14/09/2005, 12h37
  5. [langage] 2 fichier dans 1 en evitant les doublons
    Par remixxl dans le forum Langage
    Réponses: 6
    Dernier message: 26/07/2004, 17h05

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