Doctrine 1.2, i18n : Column not found: 1054 Unknown column ‘h.translated_field’ in ‘field list’
30 mai 2012 par: Benoit BonnevilleDans Doctrine 1.2, généralement sous le framework symfony 1.4.
Vous utilisez i18n et vous avez l’erreur suivante :
SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘h.translated_field’ in ‘field list’
Doctrine: Unknown column in ‘field list’ pour I18N Behaviors
Mise en situation :
Vous utilisez Doctrine 1.2 l’ORM PHP.
Votre Schema Doctrine contiens un » actAs: i18n « , c’est à dire un « Behaviors » d’internationalisation.
(i18n veux dire InternationalisatioN).
schema.yml :
MyItem: actAs: I18n: fields: [translated_field]
Puis vérifiez que dans votre fichier BaseMyItem.class.php vous avez bien :
$i18n0 = new Doctrine_Template_I18n(array( 'fields' => array( 0 => 'translated_field' ), )); $this->actAs($i18n0);
(Ce code est mal indenté, c’est un copier coller du code généré par doctrine)
Rappel du path : ./lib/model/doctrine/base/BaseMyItem.class.php
Si vous ne l’avez pas, c’est que vous n’avez pas construit votre model (php symfony build-model)
Erreur la plus fréquente : votre model est erroné.
Votre base de donnée n’a pas la table Translation dont vous avez besoin avec le champ translated_field.
Je vous laisse regarder dans la documentations Doctrine. Nous allons traitez ici d’un bug particulier.
Erreur qui n’impact que l’i18n dans certains cas :
En temps normal cette erreur n’apparaît pas et vous parvenez à instancier un objet.
Le problème est une question de majuscule dans le nom de la table principale de votre requête.
Voici un exemple de code qui ne fonctionnera pas :
Doctrine::getTable('myItem')->find(1); // any code execution and any scope change (class,function,method) ... Doctrine::getTable('MyItem')->find(1);
Bien entendu ces 2 lignes peuvent être placées n’importe ou dans votre code. C’est à dire pas exclusivement dans la même méthode,fonction ou classe.
Cela impact aussi le champ ->from() de n’importe quelle Doctrine_Query.
Correction :
Recherchez tout vos appels au méthodes statique getTable() et tout vos méthode ->from() de votre projet et corrigez la casse.
Explication :
Si cela interesse quelqu’un, Doctrine conserve en interne la déclaration du mapping de chacun des objet. Ils sont stoqués dans un tableau associatif, avec comme clef d’index , le nom de la classe, qui est insensible à la casse.
Dans ce tableau associatif vous retrouvez aussi les objet de traductions. Mais ceux ci, dépendant du nom de l’objet de base, sont sensible à la casse !
Ce tableau se trouve dans le singleton Doctrine_Manager, paramètre protected « _bound« .
Le singleton explique que peu importe ou vous exécutiez votre code, le problème est présent, tant qu’il s’agit de la même exécution de script.
Pour le visualiser je vous invite à executer :
Doctrine::getTable('myItem'); Doctrine::getTable('MyItem'); var_dump(Doctrine_Manager::getInstance());
XDEBUG est très fortement recommandé si vous ne voulez pas que le var_dump ne consomme toute votre mémoire.
Vous verrez alors :
protected '_bound' => array 'MyItem' => string 'doctrine' (length=8) 'myItemTranslation' => string 'doctrine' (length=8)
Vous pourrez constater que toute utilisation de MyItem, celui-ci ne trouvera pas sa table de Translation.
D’ou le message d’erreur qui explique qu’il ne parviens pas à trouver le champ traduit, car sans la table de Translation, Doctrine cherche le champ à l’interieur de l’objet lui même.
La 2ème raison était la bonne dans mon cas. Pas évident à trouver: je viens de passer 1 bonne heure dessus.
Merci pour ce post.