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 :

Problème Internationalisation avec Doctrine


Sujet :

ORM PHP

  1. #1
    Candidat au Club
    Inscrit en
    Novembre 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 15
    Points : 4
    Points
    4
    Par défaut Problème Internationalisation avec Doctrine
    Bonjour à tous,

    Je découvre le développement avec Symfony et après quelques jours d'utilisations, je rencontre un problème pour internationaliser mes tables Doctrine.

    Tout d'abord, je vais vous exposer la situation:
    Mon site a pour but d'afficher des voyages.
    Chaque voyages est associé à une liste de pays (par une table de liaison)

    Voici la structure de mes tables:
    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
     
    Continent:
       tableName: Continent
       actAs:
          I18n:
             fields: [nom]
       columns:
          id:   { type: integer(3), unsigned: true, primary: true, autoincrement: true }
          nom:  { type: string(15), notnull: true }
     
     
    Pays:
       tableName: Pays
       columns:
          id:                  { type: integer(4), unsigned: true, primary: true, autoincrement: true }
          continent_id:        { type: integer(3), unsigned: true, notnull: true }
          sous_continent_id:   { type: integer(4), unsigned: true }
          iso:                 { type: string(2) }
          nom:                 { type: string(100), notnull: true }
       relations:
          Continent:           { onDelete: CASCADE, local: continent_id, foreign: id }

    Dans la classe Voyage, je récupère la liste des pays puis pour chaque pays je récupère le continent. Pour cela j'ai créé une méthode dans la classe ContinentTable (est-ce correct ou y a-t-il plus simple?):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    foreach($paysList->execute() as $pays)
    {
    	$continents[] = Doctrine_Core::getTable('Continent')->getContinentByIdAndCulture($result->pays_id, 'fr');
    }
    Et voici ma méthode:

    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
     
    public function getContinentByIdAndCulture($id, $culture = 'es')
    {
    	$q = $this->createQuery('c')
    		->select('c.id, t.nom as nom')
    		->leftJoin('c.Translation t')
    		->andWhere('t.id = ?', $id)
    		->andWhere('t.lang = ?', $culture);
     
    	foreach($q->execute() as $c)
    	{
    		$continent = $c->nom;
    	}
     
    	return $continent;
    }
    Dans cette méthode si je ne spécifie pas d'alias au champ nom, je n'arrive pas à le récupérer. Est-ce normal??


    Cela fonctionne plus ou moins, mais je voudrai vraiment adopter les bonnes méthodes de travail liées à ce Framework.

    Mon autre problème est lié à la culture. Je n'arrive pas à récupérer la culture automatiquement? Dois-je la définir dans chaque contrôleur?


    Davance, merci à tous pour vos remarques et conseils.
    Hervé

  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
    Le schema :
    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
     
    continent:
       tableName: Continent
       actAs:
          I18n:
             fields: [nom]
       columns:
          nom:
             type: string(15)
             notnull: true 
     
     
    pays:
       tableName: Pays
       columns:
          continent_id:        
             type: integer
             notnull: true 
          sous_continent_id: integer(4)
          iso: string(2)
          nom:
             type: string(100)
             notnull: true
       relations:
          continent:           
             onDelete: CASCADE
             local: continent_id
             foreign: id
             foreignAlias: payss
    remis à ma sauce, plus claire, supprimé des données inutiles et le fonctionnement par défaut de Doctrine mis en place, notamment pour les champs id, auto générés.

    Juste un problème avec pays qui prend un s au singulier. La norme veut que, du côté n de la relation, on rajoute un s au nom du champs pour préciser qu'il retourne un doctrine_collection et non pas un doctrine_record. La solution serait d'utiliser nation (et nations) en lieu et place de pays et payss...

    La requête peut ce résumer à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    	$q = $this->createQuery('c')
    		->select('c.id, c.nom');
    Avec ce système, doctrine retourne le nom qui correspond à la culture de l'utilisateur. Seul problème, il va y avoir une requête pour chaque recherche de nom. On peut donc contrer la chose par :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    	$q = $this->createQuery('c')
    		->select('c.id, c.nom')
                    ->leftJoin('c.translation t');
    a noter que le champ reste celui récupéré et défini sur la table c. C'est tous l'intérêt du i18n automatique, tu ne t'occupe pas de lui, il gère.
    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
    Candidat au Club
    Inscrit en
    Novembre 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 15
    Points : 4
    Points
    4
    Par défaut
    Merci pour ta réponse rapide!
    Je vais tester ca au plus vite et reviendrai poster mes remarques

  4. #4
    Candidat au Club
    Inscrit en
    Novembre 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 15
    Points : 4
    Points
    4
    Par défaut
    Je reviens vers vous suite aux modifications proposées.

    Dans un 1er temps, j'ai modifié ma requête par celle proposée mais cela ne fonctionne pas. Il ne me récupère par la culture. Il doit me manquer une étape.

    Dans un 2e temps; j'ai modifié le schéma tel que proposé mais cela ne fonctionne pas non plus. Voici l'erreur retournée lors de la création des tables:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Invalid schema element named "I18n" at path "Continent"
    Pourriez-vous m'indiquer comment corriger mes erreurs?

    Merci beaucoup,
    Hervé

  5. #5
    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
    Pour que la requête fonctionne, il faut avoir précisé la culture de l'utilisateur dans l'objet user.

    Le message d'erreur signifie que le nom du champ défini dans le behavior i18n n'existe pas dans les columns de la base de donnée, une erreur de copie ? Ou peut-être faut-il des espaces autour du nom [ nom ], à la réflexion, c'est ainsi que je les écris en général.
    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 !

  6. #6
    Candidat au Club
    Inscrit en
    Novembre 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 15
    Points : 4
    Points
    4
    Par défaut
    Bonjour,

    Après un petit mois de "déconnexion" me revoilà dans le projet.
    La culture semble être ok car j'utilise également le helper I18n et cela fonctionne bien. Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <?php echo __('About Jobeet') ?>
    Ou alors je comprends plus...

    Voici mon code qui je pense correspond à la définition de la culture de l'utilisateur au niveau de mon fichier action (apps\frontend\modules\album\actions\actions.class.php):
    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
    class albumActions extends sfActions
    {
      public function executeIndex(sfWebRequest $request)
      {
     
    		// Lors de la 1ere connexion, on défini la langue préférée
    		if (!$request->getParameter('sf_culture'))
    		{
    			if ($this->getUser()->isFirstRequest())
    			{
    				$culture = $request->getPreferredCulture(array('fr', 'en', 'es'));
    				$this->getUser()->setCulture($culture);
    				$this->getUser()->isFirstRequest(false);
    			}
    			else
    			{
    				$culture = $this->getUser()->getCulture();
    			}
     
    			$this->redirect('localized_homepage');
    		}
    Mais dans ce cas je ne le fais peut-etre pas au bon endroit. Je souhaiterai évidemment que cela soit enregistrer de manière globale pour mon site.

    Merci pour votre aide

  7. #7
    Candidat au Club
    Inscrit en
    Novembre 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 15
    Points : 4
    Points
    4
    Par défaut
    Après quelques recherches plus poussées, je viens peut être de trouver d'où vient mon problème.

    Dans mon fichier de indexSuccess.php, je boucle sur ma liste d'album:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    foreach ($albums as $i => $album)
    Jusque là, tout va bien.

    Ensuite dans mon code, pour chaque album, je récupère des infos:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (count($infos = $album->getInfosPays()) > 0)
    Puis dans cette fonction, j'ai pas mal de code dont certaines requêtes qui devraient utiliser la fameuse culture. Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $q = $this->createQuery('c')
    			->select('c.id, c.nom')
    			->leftJoin('c.translation t')
    			->andWhere('t.id = ?', $id);
    Cette requête n'est pas juste, mais disons que c'est à ce moment là que je souhaite faire des requêtes avec la culture.

    Voilà, je pense que la clef de mon problème se situe par là.

    Encore merci d'avance pour l'aide apportée.

  8. #8
    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
    Pour ce qui est de la première question sur l'utilisation su sf_culture. Il est évident que le mettre dans une action, quel-quel soit n'est pas l'idéal. De plus la méthode isFirstRequest() n'existe pas dans l'API de base, donc je supposer que tu l'as mise. Dans la "norme" symfony, il faudrait deux méthodes, une isFirstRequest() et une autre setFirstRequest().

    L'endroit idéal pour ce type de traitement serait dans la chaine de filtre de l'application, le code serait donc exécuté lors de chaque appel au contrôleur. Par contre, je ne pense pas que le traitement soit optimal, en effet, si l'utilisateur décide d'afficher une page dans une autre culture en changeant simplement la langue dans l'url, sa demande ne sera pas prise en compte, ce qui n'est pas le comportement qu'il attendra de l'application et risque de générer des pertes de personas qui ne seraient pas satisfaites de ce comportement.

    Donc, si l'on met la culture dans l'url, ce qui me semble le mieux pour un utilisateur non identifié, il faut la prendre en compte à chaque requête, que l'utilisateur en soit ou non à sa première requête. Si par contre, il s'agit d'initialiser la langue lors de la première requête, symfony le fait déjà, automatiquement, autant le laisser faire.



    Dans la deuxième question. Il est plus simple de ne pas tenter d'intervenir dans les liaisons avec les tables de translation. Si tu initialises un objet livre avec un numéro isbn, nom d'auteur et un nom de livre et description, les deux derniers champs sont internationalisés. Tu vas récupérer le numéro isbn par un $livre->getIsbn() et la description par $livre->getDescription(), qui te retournera la bonne description, sans qu'il ne soit nécessaire de préciser quoi que cela soit dans la requête.

    Le mieux est souvent de laisser symfony gérer ce qu'il sait gérer (ou doctrine dans ce cas si).
    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 !

  9. #9
    Candidat au Club
    Inscrit en
    Novembre 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 15
    Points : 4
    Points
    4
    Par défaut
    Bonjour,

    Merci pour tes précieuses informations.
    Toutefois j'ai peur de ne pas tout comprendre.

    Je débute encore avec symfony et je cherche vraiment à écrire mon code et à organiser mon app de la manière la plus propre.

    Pourriez-vous me dire dans quel fichier il serait opportun de gérer mes langues? si vous aviez un bout de code ou un lien ca serait génial!


    Pour les appels du style $livre->getNom(), je ne sais pas trop comment procéder car dan mon cas ma fonction getInfos() retourne des infos qui sont stockées dans d'autres tables.

    Pour être plus concret:
    J'ai plusieurs tables (continent, pays, ville)
    pour un voyage ou album données, getInfos me retourne la liste des continents, pays et villes qui composent ce voyage. Du coup derrière j'ai plusieurs requêtes qui me permettent de composer un array avec les données à retourner.

    J'espère être assez clair et pas trop chiant. J'ai beau lire et relire le tuto Jobeet, je ne m'en sors pas...mais je souhaite vraiment découvrir ce framework qui me semble vraiment intéressant.

  10. #10
    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
    Il faudrait sans aucun doute que quelqu'un (moi ?) prenne un jour le temps pour écrire un tuto du genre, les bonnes pratiques de développement sous symfony à l'intention des débutants...

    Par contre, tu poses beaucoup de questions (c'est bien), mais leur traitement total mériterait plusieurs livres...

    Pour ce qui est de l'internationalisation.
    L'emplacement de la traduction dépend du type d'informations.

    Pour les libellés et autres écritures fixes (aide, message d'erreurs,...) il faut les gérer dans des fichiers xlif avec la fonction __() au niveau des templates. Plus d'informations dans le jour 19 de jobeet.

    Pour ce qui est des tables changeantes (articles, catégories, ...), toutes les données qui peuvent être amenées à évoluer dans la vie d'une application et d'une installation à une autre, il faut les stocker dans les tables internationalisée, tel que tu l'as fait. Tu as un bon exemple toujours dans le jour 19 de jobeet, le recopier ici n'aurait pas grand intérêt.

    Il nous reste les trucs bizarre du genre libellés stocké dans des tables et non sujet à varier au cours de la vie de l'application (titre par exemple, soit Monsieur, Madame, Mademoiselle ou encore sexe Masculin ou Féminin). Là, je n'ai pas trouvé de bon emplacements, tous dépend du traitement que tu leur fais subir ensuite, mais c'est variant, soit dans les tables, soit dans des fichiers de traduction.


    Pour ce qui est des enregistrements et des getXxxx()
    C'est sur que ce n'est pas évident

    Dans les règles de base pour l'écriture du shema.yml :
    • pas de majuscule en debut d'aucun nom de table ou champ, éventuellement, en millieu pour séparer un nom trop long.
    • pas de nom de champ et encore moins de table au pluriel, un mot qui finirait naturellement par un "s" à tout intérêt à être modifier en un autre nom.
    • les liaisons "naturel" (au sens de doctrine une liaison 1-n) doivent n'être définie que sur une des deux tables qui constituent la liaison, de préférence la table "n" de la liaison.

    Il y a d'autre règles pour des cas plus particulier. Je ne vais pas mettre d'exemple, mais si tu as un shema.yml (pas trop long) j'y jetterais un œil attentif et apporterais volontiers les modifications que j'y aurais apporté s'il avait été miens, en les commentant.

    Maintenant, il y a un truc qui est un peu galère, c'est le getXxxx(). En effet, il peut nous retourner plusieurs choses suivant le cas :
    • le plus souvent une données, le nom (getNom() ), l'id (getId() )....
    • un enregistrement d'un table (objet enfant de sfRecord ) pour le côté 1, dans le cas d'une relation 1-n. Exemple : article <1---n> commentaire si on est dans un objet commentaire, on récupère l'objet article correspondant par ->getArticle(). Si les relations sont correctement définies. En cherchant plus loin, on peut, toujours depuis notre commentaire récupérer l'objet de l'article dont dépend le commentaire par ->getArticle()->getObjet().
    • un jeu d'objet (objet doctrine_collection) ou un lot d'enregistrement, deux noms différents pour une même chose. Il faut alors les parcourir à l'aide d'un foreach ou autre outils php. En gardant l'exemple précédent, on va, pour un article, récupérer les commentaires correspondants par->getCommentaires. Tiens, un "s" ! En effet, on va, dans notre relation, mettre un "s" à la fin du nom de la relation qui retourne plusieurs enregistrements, ce qui nous permettra de nous y retrouver.

    Il faut bien faire attention, pour éviter les confusions, de ne pas avoir un nom de champ et un nom de relation identique dans notre description des tables, au risque de ne pas savoir ce que va nous retourner doctrine.


    J'espère avoir apporté un rien de lumière sur les deux questions. Poste ton schema.yml, je le commenterais.
    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 !

  11. #11
    Candidat au Club
    Inscrit en
    Novembre 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 15
    Points : 4
    Points
    4
    Par défaut
    Voici mon schéma mis à jour par rapport aux différentes remarques:

    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
     
     
    Continent:
       tableName: Continent
       actAs:
          I18n:
             fields: [nom]
       columns:
          nom:  { type: string(15), notnull: true }
     
     
    SousContinent:
       tableName: SousContinent
       actAs:
          I18n:
             fields: [nom]
       columns:
          continent_id:  { type: integer, notnull: true }
          nom:           { type: string(50), notnull: true }
       relations:
          Continent:     { onDelete: CASCADE, local: continent_id, foreign: id, foreignAlias: Continents }
     
     
    Nation:
       tableName: Nation
       actAs:
          I18n:
             fields: [nom]
       columns:
          continent_id:        { type: integer, notnull: true }
          sous_continent_id:   { type: integer }
          iso:                 { type: string(2) }
          nom:                 { type: string(100), notnull: true }
       relations:
          Continent:           { onDelete: CASCADE, local: continent_id, foreign: id, foreignAlias: Continents }
          SousContinent:       { onDelete: CASCADE, local: sous_continent_id, foreign: id, foreignAlias: SousContinents }
     
     
    Voyage:
       tableName: Voyage
       actAs:
          Timestampable: ~
          I18n:
             fields: [titre, description]
       columns:
          titre:         { type: string(100), notnull: true }
          description:   { type: string(4000) }
          dossier:       { type: string(100) }
          date_de_debut: { type: date, notnull: true }
          date_de_fin:   { type: date }
          est_public:    { type: boolean, notnull: true, default: 1 }
          est_visible:   { type: boolean, notnull: true, default: 0 }
     
     
    VoyageNation:
       tableName: VoyageNation
       columns:
          voyage_id:  { type: integer, primary: true }
          nation_id:  { type: integer, primary: true }
       relations:
          Voyage:     { onDelete: CASCADE, local: voyage_id, foreign: id, foreignAlias: Voyages }
          Nation:     { onDelete: CASCADE, local: nation_id, foreign: id, foreignAlias: Nations }
     
     
    Tag:
       tableName: Tag
       actAs:
          I18n:
             fields: [nom]
       columns:
          nom:  { type: string(100), notnull: true }
     
     
    VoyageTag:
       tableName: VoyageTag
       columns:
          voyage_id:  { type: integer, primary: true }
          tag_id:     { type: integer, primary: true }
       relations:
          Voyage:     { onDelete: CASCADE, local: voyage_id, foreign: id, foreignAlias: Voyages }
          Tag:        { onDelete: CASCADE, local: lieu_id, foreign: id, foreignAlias: Tags }
     
     
    Photo:
       tableName: Photo
       actAs:
          Timestampable: ~
          I18n:
             field: [description]
       columns:
          voyage_id:     { type: integer, notnull: true }
          nom:           { type: string(50) }
          description:   { type: string(150) }
          position:      { type: integer }
          est_publique:  { type: boolean, notnull: true, default: 1 }
       relations:
          Voyage:        { onDelete: CASCADE, local: voyage_id, foreign: id, foreignAlias: Voyages }
     
     
    Utilisateur:
       tableName: Utilisateur
       actAs:
          Timestampable: ~
       columns:
          username:            { type: string(20), notnull: true, unique: true }
          password:            { type: string(40), notnull: true }
          nom:                 { type: string(50) }
          prenom:              { type: string(50) }
          statut:              { type: string(15), notnull: true, default: utilisateur }
          email:               { type: string(50), notnull: true }
          tel_mobile:          { type: string(20) }
          derniere_connexion:  { type: datetime }
          derniere_ip:         { type: string(20) }

  12. #12
    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
    Revu et interprété à ma sauce :
    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
     
    continent:
       tableName: continent
       actAs:
          i18n:
             fields: [nom]
       columns:
          nom:  { type: string(15), notnull: true }
     
    sousContinent:
       tableName: sous_continent
       actAs:
          i18n:
             fields: [nom]
       columns:
          continent_id:  { type: integer, notnull: true }
          nom:           { type: string(50), notnull: true }
       relations:
          continent:     { onDelete: CASCADE, local: continent_id, foreign: id, foreignAlias: sousContinents}
     
    nation:
       tableName: nation
       actAs:
          i18n:
             fields: [nom]
       columns:
          sous_continent_id:   { type: integer }
          iso:                 { type: string(2) }
          nom:                 { type: string(100), notnull: true }
       relations:
          sousContinent:       { onDelete: CASCADE, local: sous_continent_id, foreign: id, foreignAlias: nations }
     
    voyage:
       tableName: voyage
       actAs:
          Timestampable: ~
          i18n:
             fields: [titre, description]
       columns:
          titre:         { type: string(100), notnull: true }
          description:   { type: string(4000) }
          dossier:       { type: string(100) }
          date_de_debut: { type: date, notnull: true }
          date_de_fin:   { type: date }
          est_public:    { type: boolean, notnull: true, default: 1 }
          est_visible:   { type: boolean, notnull: true, default: 0 }
       relations:
          nations:
            class: nation
            foreignAlias: voyages
            refClass: voyageNation
     
    voyageNation:
       tableName: voyage_nation
       options:
          symfony:
             form:      false
             filter:    false
       columns:
          voyage_id:  { type: integer, primary: true }
          nation_id:  { type: integer, primary: true }
       relations:
          voyage:     { onDelete: CASCADE, local: voyage_id, foreign: id, foreignAlias: voyageNations }
          nation:     { onDelete: CASCADE, local: nation_id, foreign: id, foreignAlias: voyageNations }
     
    tag:
       tableName: tag
       actAs:
          i18n:
             fields: [nom]
       columns:
          nom:  { type: string(100), notnull: true }
       relations:
         voyages:
           class: voyage
           foreignAlias: tags
           refClass: voyageTag
     
    voyageTag:
       tableName: voyage_tag
       options:
          symfony:
             form:      false
             filter:    false
       columns:
          voyage_id:  { type: integer, primary: true }
          tag_id:     { type: integer, primary: true }
       relations:
          voyage:     { onDelete: CASCADE, local: voyage_id, foreign: id, foreignAlias: voyages }
          tag:        { onDelete: CASCADE, local: tag_id, foreign: id, foreignAlias: tags }
     
     
    photo:
       tableName: photo
       actAs:
          Timestampable: ~
          i18n:
             fields: [description]
       columns:
          voyage_id:     { type: integer, notnull: true }
          nom:           { type: string(50) }
          description:   { type: string(150) }
          position:      { type: integer }
          est_publique:  { type: boolean, notnull: true, default: 1 }
       relations:
          voyage:        { onDelete: CASCADE, local: voyage_id, foreign: id, foreignAlias: photos }
     
    utilisateur:
       tableName: utilisateur
       actAs:
          Timestampable: ~
       columns:
          username:            { type: string(20), notnull: true, unique: true }
          password:            { type: string(40), notnull: true }
          nom:                 { type: string(50) }
          prenom:              { type: string(50) }
          statut:              { type: string(15), notnull: true, default: utilisateur }
          email:               { type: string(50), notnull: true }
          tel_mobile:          { type: string(20) }
          derniere_connexion:  { type: datetime }
          derniere_ip:         { type: string(20) }
    Modifications proposées :
    • le nom des tables commence toujours par une minuscule
    • le foreignAlias est le nom de la relation vue de l'autre côté. Donc pour, par exemple, la relation entre "continent" et "sousContient", le foreignAlias va être le nom de cette relation vue du côté de l'objet continent, c'est pourquoi je l'appellerais plutôt "sousContinents" avec un "s" pour indiquer qu'a un continent correspond plusieurs "sousContinent".
    • Table nation, je supprimerais le lien vers continent, il n'apporte rien, n'est pas conforme aux formes normal et va être lourd et difficile à maintenir. Dans tous les cas, le continent définis dans nation ne pourra être diffèrent de celui de sousContinent...
    • voyage et nation, cas particulier de liaisons, les deux tables sont dans le cadre d'une liaison n-n, on va donc créer ici (c'est un des cas particulier non traités dans le message précédant) trois relations, ce qui va permettre, depuis un objet voyage de récupérer la liste des nations visitées par ->getNations(), sans avoir a gérer la table voyageNation, doctrine s'en charge.
    • voyageNation, la génération du form et du filter sont désactivé, en principe cet objet ne sera jamais utilisé seul, mais toujours en conjonction avec voyage ou nation, pourquoi encombrer nos fichiers de données inutiles.
    • table tag et voyage, même remarques que pour voyage et nation.
    • table voyageTag, relations, tag, correction du local de lieu_id en tag_id.
    • table photo, dans i18n, il faut field doit s'écrire fields.
    • table utilisateur. Certe, on peut fonctionner ainsi. Cepandant, je pense qu'il pourrait être intéressant de jeter un oeil attentif aux plugins :
      • sfDoctrineGuardPlugin pour la gestion des utilisateurs et des droits et de la connexion authentification,
      • sfDoctrineApplyPlugin pour la création des comptes, l'enrichissement des champs de base de sfDoctrineGuardPlugin, la récupération des mots de passe perdus, la vérification par email lors de la créations.
      Toutes fonctions automatisées dans ces deux plugins, autant de code en moins a écrire, mais une prise en mains un peu lourde, il faut suer pour les mériter (surtout sfDoctrineApplyPlugin). Personnellement, je les utilises systématiquement lorsque j'ai des droits et des connexions à gérer.


    C'est une structure un peu complexe, mais je pense qu'ainsi elle devrait fonctionner et te donner entière satisfaction.

    Bonne chance,
    Michel
    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 !

  13. #13
    Candidat au Club
    Inscrit en
    Novembre 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 15
    Points : 4
    Points
    4
    Par défaut
    j'ai mis à jour mon schéma comme vu précédemment.
    Mais j'ai une erreur sur ce morceau de code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    options:
          symfony:
             form:      false
             filter:    false
    En le supprimant cela fonctionne correctement.

    Toutefois, j'ai les anciennes tables qui reviennent dans mon schéma lorsque je fais un doctrine:build-schema.

    Y a t'il un moyen de renettoyer tout ca sans recommencer le projet de zéro?

    EDIT: conccernant mes fonctions je dois les adapter au nouveau schéma.
    Je vous tiendrai informé

  14. #14
    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
    Tu dis utiliser une 1.4, j'ai testé sur une 1.4 et la construction se passe sans problème, (environnement wamp). J'utilise ces commandes régulièrement sans jamais de problèmes...

    D'un autre côté, si elle n'y son pas, on a juste 4 fichiers inutiles de plus dans le projet, ce qui n'est pas très grave.

    Tu as la commande doctrine:clean-model-files qui permet de nettoyer ton modèle.

    Effectivement, il va y avoir quelques adaptations à faire, mais le schéma est plus solide, le gain devrait être plus important que la perte en adaptation.
    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 !

  15. #15
    Candidat au Club
    Inscrit en
    Novembre 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 15
    Points : 4
    Points
    4
    Par défaut
    merci c'est la commande qu'il me manquait
    je vais continuer à travailler sur les fonctions.

  16. #16
    Candidat au Club
    Inscrit en
    Novembre 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 15
    Points : 4
    Points
    4
    Par défaut
    Salut michel,

    Suite à mon nouveau schéma j'essaie d'insérer un jeu de données via un fichier fixture que voici:
    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
     
    Continent:
      afrique:
        Translation:
          fr:
            nom: Afrique
          en:
            nom: Africa
          es:
            nom: África
      amerique:
        Translation:
          fr:
            nom: Amérique
          en:
            nom: America
          es:
            nom: América
      asie:
        Translation:
          fr:
            nom: Asie
          en:
            nom: Asia
          es:
            nom: Asia
      europe:
        Translation:
          fr:
            nom: Europe
          en:
            nom: Europe
          es:
            nom: Europa
      oceanie:
        Translation:
          fr:
            nom: Océanie
          en:
            nom: Oceania
          es:
            nom: Oceanía
      antartique:
        Translation:
          fr:
            nom: Antartique
          en:
            nom: Antarctica
          es:
            nom: Antártida
    Pour info j'ai conservé les majuscules dans les noms de mes tables par habitude

    Quand je load les data j'ai l'erreur suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Unknown record property / related component "translation" on "Continent"
    J'ai regardé au niveau de ma db et je vois un champ nom qui me semble suspect dans la table Continent:

    Continent (#id, nom)
    Continent_translation (#id, #lang, nom)


    J'ai une autre question qui n'a rien à voir: est-il facile de mettre à jour symfony? Je suis en 1.4.3 et j'ai vu dans un autre post ou tu répondais que dans les versions suivantes le champ lang est remplacé par culture.
    Travaillant avec l'I18n, cela serait-il intéressant de faire l'upgrade?

  17. #17
    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
    Peux-tu mettre le schema.yml que tu as décidé de garder ? Que je puisse tester.

    En principe tu peux sans danger passer de la 1.4.3 à la 1.4.6 actuel. Il m'étonnerait que tu aies utilisé les fonctions modifiées, et, en principe, dans un même numéro de sous version, la compatibilité ascendante est prévue. Perso, je n'ai rencontré aucune difficulté lors des mises à jour, au contraire.

    Et effectivement, cela pourrait simplifier l'utilisation des langues et de la culture. Et sur un projet tel que le tiens, cela me semble primordial.
    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 !

  18. #18
    Candidat au Club
    Inscrit en
    Novembre 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 15
    Points : 4
    Points
    4
    Par défaut
    Le voilà:

    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
     
    Continent:
       tableName: Continent
       actAs:
          I18n:
             fields: [nom]
       columns:
          nom:  { type: string(15), notnull: true }
     
     
    SousContinent:
       tableName: SousContinent
       actAs:
          I18n:
             fields: [nom]
       columns:
          continent_id:  { type: integer, notnull: true }
          nom:           { type: string(50), notnull: true }
       relations:
          Continent:     { onDelete: CASCADE, local: continent_id, foreign: id, foreignAlias: SousContinents }
     
     
    Nation:
       tableName: Nation
       actAs:
          I18n:
             fields: [nom]
       columns:
          continent_id:        { type: integer, notnull: true }
          sous_continent_id:   { type: integer }
          iso:                 { type: string(2) }
          nom:                 { type: string(100), notnull: true }
       relations:
          Continent:           { onDelete: CASCADE, local: continent_id, foreign: id, foreignAlias: Nations }
          SousContinent:       { onDelete: CASCADE, local: sous_continent_id, foreign: id, foreignAlias: Nations }
     
     
    Voyage:
       tableName: Voyage
       actAs:
          Timestampable: ~
          I18n:
             fields: [titre, description]
       columns:
          titre:         { type: string(100), notnull: true }
          description:   { type: string(4000) }
          dossier:       { type: string(100) }
          date_de_debut: { type: date, notnull: true }
          date_de_fin:   { type: date }
          est_public:    { type: boolean, notnull: true, default: 1 }
          est_visible:   { type: boolean, notnull: true, default: 0 }
     
     
    VoyageNation:
       tableName: VoyageNation
       columns:
          voyage_id:  { type: integer, primary: true }
          nation_id:  { type: integer, primary: true }
       relations:
          Voyage:     { onDelete: CASCADE, local: voyage_id, foreign: id }
          Nation:     { onDelete: CASCADE, local: nation_id, foreign: id }
     
     
    Tag:
       tableName: Tag
       actAs:
          I18n:
             fields: [nom]
       columns:
          nom:  { type: string(100), notnull: true }
     
     
    VoyageTag:
       tableName: VoyageTag
       columns:
          voyage_id:  { type: integer, primary: true }
          tag_id:     { type: integer, primary: true }
       relations:
          Voyage:     { onDelete: CASCADE, local: voyage_id, foreign: id }
          Tag:        { onDelete: CASCADE, local: tag_id, foreign: id }
     
     
    Photo:
       tableName: Photo
       actAs:
          Timestampable: ~
          I18n:
             fields:  [description]
       columns:
          voyage_id:     { type: integer, notnull: true }
          nom:           { type: string(50) }
          description:   { type: string(150) }
          position:      { type: integer }
          est_publique:  { type: boolean, notnull: true, default: 1 }
       relations:
          Voyage:        { onDelete: CASCADE, local: voyage_id, foreign: id, foreignAlias: Voyages }
     
     
    Utilisateur:
       tableName: Utilisateur
       actAs:
          Timestampable: ~
       columns:
          username:            { type: string(20), notnull: true, unique: true }
          password:            { type: string(40), notnull: true }
          nom:                 { type: string(50) }
          prenom:              { type: string(50) }
          statut:              { type: string(15), notnull: true, default: utilisateur }
          email:               { type: string(50), notnull: true }
          tel_mobile:          { type: string(20) }
          derniere_connexion:  { type: datetime }
          derniere_ip:         { type: string(20) }

  19. #19
    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
    J'ai un peu re corrigé le shema, il manquait deux liaisons entre voyages et nations et entre voyages et tags. Elle vont être essentielles pour la suite, surtout pour les fixatures...

    Le fichier rectifié :
    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
     
    Continent:
       tableName: Continent
       actAs:
          I18n:
             fields: [nom]
       columns:
          nom:  { type: string(15), notnull: true }
     
     
    SousContinent:
       tableName: SousContinent
       actAs:
          I18n:
             fields: [nom]
       columns:
          continent_id:  { type: integer, notnull: true }
          nom:           { type: string(50), notnull: true }
       relations:
          Continent:     { onDelete: CASCADE, local: continent_id, foreign: id, foreignAlias: SousContinents }
     
     
    Nation:
       tableName: Nation
       actAs:
          I18n:
             fields: [nom]
       columns:
          continent_id:        { type: integer, notnull: true }
          sous_continent_id:   { type: integer }
          iso:                 { type: string(2) }
          nom:                 { type: string(100), notnull: true }
       relations:
          Continent:           { onDelete: CASCADE, local: continent_id, foreign: id, foreignAlias: Nations }
          SousContinent:       { onDelete: CASCADE, local: sous_continent_id, foreign: id, foreignAlias: Nations }
     
     
    Voyage:
       tableName: Voyage
       actAs:
          Timestampable: ~
          I18n:
             fields: [titre, description]
       columns:
          titre:         { type: string(100), notnull: true }
          description:   { type: string(4000) }
          dossier:       { type: string(100) }
          date_de_debut: { type: date, notnull: true }
          date_de_fin:   { type: date }
          est_public:    { type: boolean, notnull: true, default: 1 }
          est_visible:   { type: boolean, notnull: true, default: 0 }
       relations:
          Nations:
            class: Nation
            foreignAlias: Voyages
            refClass: VoyageNation
     
     
    VoyageNation:
       tableName: VoyageNation
       columns:
          voyage_id:  { type: integer, primary: true }
          nation_id:  { type: integer, primary: true }
       relations:
          Voyage:     { onDelete: CASCADE, local: voyage_id, foreign: id }
          Nation:     { onDelete: CASCADE, local: nation_id, foreign: id }
     
     
    Tag:
       tableName: Tag
       actAs:
          I18n:
             fields: [nom]
       columns:
          nom:  { type: string(100), notnull: true }
       relations:
         Voyages:
           class: Voyage
           foreignAlias: Tags
           refClass: VoyageTag
     
     
    VoyageTag:
       tableName: VoyageTag
       columns:
          voyage_id:  { type: integer, primary: true }
          tag_id:     { type: integer, primary: true }
       relations:
          Voyage:     { onDelete: CASCADE, local: voyage_id, foreign: id }
          Tag:        { onDelete: CASCADE, local: tag_id, foreign: id }
     
     
    Photo:
       tableName: Photo
       actAs:
          Timestampable: ~
          I18n:
             fields:  [description]
       columns:
          voyage_id:     { type: integer, notnull: true }
          nom:           { type: string(50) }
          description:   { type: string(150) }
          position:      { type: integer }
          est_publique:  { type: boolean, notnull: true, default: 1 }
       relations:
          Voyage:        { onDelete: CASCADE, local: voyage_id, foreign: id, foreignAlias: Voyages }
     
     
    Utilisateur:
       tableName: Utilisateur
       actAs:
          Timestampable: ~
       columns:
          username:            { type: string(20), notnull: true, unique: true }
          password:            { type: string(40), notnull: true }
          nom:                 { type: string(50) }
          prenom:              { type: string(50) }
          statut:              { type: string(15), notnull: true, default: utilisateur }
          email:               { type: string(50), notnull: true }
          tel_mobile:          { type: string(20) }
          derniere_connexion:  { type: datetime }
          derniere_ip:         { type: string(20) }
    J'ai donc charger dans une appli de test avec le fixature, non retouché et tous passe bien.

    La seul différence est la version de symfony. Essayes avec la 1.4.6.
    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 !

  20. #20
    Candidat au Club
    Inscrit en
    Novembre 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 15
    Points : 4
    Points
    4
    Par défaut
    Alors, j'ai remplacé mon dossier symfony dans \lib\vendor par celui de symfony 1.4.6.
    Dans le frontend de dev je vois bien la version 1.4.6 donc j'en déduis que tout est bon.


    Par contre, j'ai copié le schéma que tu me proposes, mais j'ai toujours la même erreur concernant les fixtures...

    Ce pourrait-il que mon environnement soit corrompu? Pourtant les tables sont bien créées. Je suis un peu perdu...

    De plus, pourrais-tu m'expliquer pourquoi tu as rajouté ces relations de cette manière avec le refClass?

    Merci!!!

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 1
    Dernier message: 25/08/2013, 01h02
  2. [2.x] Problème avec doctrine:database:create
    Par Jugurth dans le forum Symfony
    Réponses: 3
    Dernier message: 25/04/2012, 13h06
  3. [1.x] Problème de relation 1-1 avec Doctrine
    Par Niki59 dans le forum Symfony
    Réponses: 6
    Dernier message: 05/04/2011, 14h58
  4. [1.x] Problème avec doctrine:generate-admin
    Par climbo dans le forum Débuter
    Réponses: 5
    Dernier message: 24/02/2011, 10h04
  5. [ZF 1.7] problème avec doctrine + oracle sur zendframework
    Par cornnery dans le forum Zend_Db
    Réponses: 1
    Dernier message: 09/03/2009, 17h41

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