[DC-1031] CLONE -Multiple connections and i18n (raised as unresolved - original ticket marked as resolved) Created: 23/Aug/11  Updated: 28/Mar/12

Status: Open
Project: Doctrine 1
Component/s: Connection, I18n
Affects Version/s: 1.2.2, 1.2.3
Fix Version/s: 1.2.3

Type: Bug Priority: Blocker
Reporter: James Bell Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

MySQL 5.1.37
PHP 5.2.11
symfony 1.2.11 DEV

symfony 1.4.13
PHP 5.3.6
Postgres 8.4.8



 Description   

I used to work with a single database named "doctrine". The query was working properly.

I then decided to use 2 databases so I got my schema like this:

connection: doctrine

Category:
actAs:
I18n:
actAs:
Sluggable:
fields: [name]
Timestampable: ~
fields: [name, description]
columns:
id: ~
name:
type: string(255)
notnull: true
description: string

User:
connection: second
columns:
id: ~
name:
type: string(255)
notnull: true

I did setup my connections in config/databases.yml this way:

all:
doctrine:
// ....
second:
// ....

build-model, build-forms, build-filters and cc got ran. But now, I got an exception saying the "Translation" relation doesn't exist. The Base Models include correctly the bindComponent line:

Doctrine_Manager::getInstance()->bindComponent('Category', 'doctrine');

For now, I managed to kind of fixing it with simply swapping the databases order in my config/databases.yml and it's now working again perfectly.

I forgot to mention that in the CategoryTable when i call $this->getConnection()->getName(), it outputs "second"



 Comments   
Comment by James Bell [ 23/Aug/11 ]

Original issue: DC-363 (http://www.doctrine-project.org/jira/browse/DC-363)

There are some additional comments in there that explain the issue as currently being seen in released versions of Doctrine 1.2. Can I help verify that this is the same ticket?

What is needed to help with debug (in addition to the extra information already provided)?

Comment by Andy.L [ 28/Mar/12 ]

meet the same issue and it really blocked my project, seems no one will maintain 1.x. I'm considering whether to replace symfony 1.4 with 2.0.





[DC-880] Versionable + I18n creates additional migration with irrelevant data Created: 06/Oct/10  Updated: 17/Apr/14

Status: Open
Project: Doctrine 1
Component/s: Behaviors, I18n, Migrations, Relations
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Thomas Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 1
Labels: None
Environment:

PHP 5.2, Symfony 1.4, Diem 5.1, Doctrine 1.2.2



 Description   

First run of generate-migrations-diff and migrate creates 2 migration diff files. First one for new tables, second one for new indexes and foreign keys. Than if I run generate-migrations-diff again another version is created although nothing was changed and following is inside:

  • 1st entry tries to drop a foreign key never been created and not existing in file
  • next entry tries to create a foreign key already existing
  • 3rd entry tries to create an existing index

After a long try and errorI found out that it's only happening with I18n plus Versionable behavior.

As I already have spent much time for a report please have also a look at: http://forum.diem-project.org/viewtopic.php?f=2&t=173&sid=5e0e3349c0e15a169bc9990a3104b3f6#p465

As I'm quite new to Doctrine and Symfony systems I cannot get further, but willing for more investigation if just one could give me a hint where to start.



 Comments   
Comment by Andrew Coulton [ 10/Oct/10 ]

I think this is because the versionable behaviour doesn't define a table name in the Doctrine_Template_Versionable class. As a result, if using model prefixes, the prefixes are not discarded from the table names when the behaviour model classes are built. This means that the tables have different names to what is expected, so they have different index keys, so the indexes are dropped and recreated as part of the migration.

I have committed unit tests and patch for this issue (which applies to Searchable also) to http://github.com/acoulton/doctrine1/tree/DC-880

Comment by Daniele Dore [ 19/Sep/11 ]

I experienced the same problem in the latest version 1.2.4, and the patch proposed by Andrew Coulton solves the problem.
Why the fix is not included in official release?





[DC-831] Importing fixtures fails when GoogleI18n used with "Couldn't create collection index. Record field 'lang' was null." Created: 17/Aug/10  Updated: 17/Apr/14

Status: Open
Project: Doctrine 1
Component/s: Data Fixtures, I18n, Import/Export
Affects Version/s: 1.2.2, 1.2.3
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Jakub Argasiński Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Mac OS X 10.6.4, Zend Server CE 5.0.2 (irrelevant, I guess)


Attachments: Text File fix_google18n_and_similiar_import_problem.patch    

 Description   

There's a problem with Doctrine_Data_Import. When trying to load a fixture record with translations, and GoogleI18n (or similar) instead of I18n is used (via actAs()), the following crash happens:
Couldn't create collection index. Record field 'lang' was null.

#0 /Users/argasek/Sites/fwm/library/doctrine/Doctrine/Access.php(131): Doctrine_Collection->add(Object(Fwm_Shop_Catalog_CategoryTranslation))
#1 /Users/argasek/Sites/test/library/doctrine/Doctrine/Data/Import.php(241): Doctrine_Access->offsetSet(NULL, Object(Test_Shop_Catalog_CategoryTranslation))
#2 /Users/argasek/Sites/test/library/doctrine/Doctrine/Data/Import.php(335): Doctrine_Data_Import->_processRow('(catalog_catego...', Array)
#3 /Users/argasek/Sites/test/library/doctrine/Doctrine/Data/Import.php(118): Doctrine_Data_Import->_loadData(Array)
#4 /Users/argasek/Sites/test/library/doctrine/Doctrine/Data.php(222): Doctrine_Data_Import->doImport(false)
#5 /Users/argasek/Sites/test/library/doctrine/Doctrine/Core.php(1011): Doctrine_Data->importData('/Users/argasek/...', 'yml', Array, false)
#6 /Users/argasek/Sites/test/library/doctrine/Doctrine/Task/LoadData.php(43): Doctrine_Core::loadData('/Users/argasek/...', false)
#7 /Users/argasek/Sites/test/library/doctrine/Doctrine/Cli.php(516): Doctrine_Task_LoadData->execute()
#8 /Users/argasek/Sites/test/library/doctrine/Doctrine/Cli.php(498): Doctrine_Cli->executeTask(Object(Doctrine_Task_LoadData), Array)
#9 /Users/argasek/Sites/test/library/doctrine/Doctrine/Cli.php(452): Doctrine_Cli->_run(Array)
#10 /Users/argasek/Sites/test/scripts/doctrine-cli.php(29): Doctrine_Cli->run(Array)
#11

{main}

I have narrowed down the problem to the line 135 of Doctrine/Data/Import.php, ie.

if ($table->hasRelation($key) && is_array($value) && ! $table->hasTemplate('Doctrine_Template_I18n')) {

In case of GoogleI18n, $table->hasTemplate('Doctrine_Template_I18n') returns false.

I have no idea how to patch this in a sane way. Adding another condition (&& ! $table->hasTemplate('Doctrine_Template_GoogleI18n') serves well as a workaround, but such condition would be required for any class similar to Doctrine_Template_GoogleI18n. I guess the condition should check if it's a Doctrine_Template_I18n template or any template iherited from this class?...



 Comments   
Comment by Jakub Argasiński [ 17/Aug/10 ]

I have provided a quick workaround patch for this problem, with an approach described in my report, ie. checking whether table has a template being an instance of or a child of Doctrine_Template_I18n.





[DC-806] i8n behavior Created: 31/Jul/10  Updated: 31/Jul/10

Status: Open
Project: Doctrine 1
Component/s: I18n
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Fabien MEYNARD Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Symfony 1.4.0, PHP 5.2.6 & 5.3.1


Attachments: PNG File Capture d’écran 2010-07-30 à 12.43.50.png    

 Description   

hi everyone

I'm trying to use the Doctrine i18n behavior but ... something wrong happen!

I have this Doctrine_Connection_Mysql_Exception :

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'p.label' in 'field list' ( ie : linked screenshot )

with this request :


Doctrine_Query::create()->from('OrderProduct o')
->leftJoin('o.Product p')
->addWhere('o.order_id = ?', $currentOrderId)
->orderBy('o.created_at ASC')
->execute();

I don't understand why doctrine try to get the label field from "Product", this field is in the Translation table :s

Here an extract from my schema.yml :

Product:
tableName: product
actAs:
I18n:
fields: [label, label_2]
columns:
code:

{type: string(64), notnull: true, primary: true}

label:

{type: string(64)}

label_2:

{type: string(64)}

i don't know if my problem is in my code ( i don't think ), in Doctrine or in Symfony implementation of doctrine and thats why i post this message.

If you want more details ask me I have one working copy "freezed" just for this bug ( and for my work i use a system without i18n behavior :s )

thx in advance






[DC-779] sf1.4 i18n form create/update item extra insert Created: 08/Jul/10  Updated: 14/Oct/10

Status: Open
Project: Doctrine 1
Component/s: I18n
Affects Version/s: 1.2.2
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Tim Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 1
Labels: None
Environment:

problem arises \w Symfony 1.4.6 on Mac OS X 10.6.4 with Mysql 5.1.38 and a also on Ubuntu 10.04 Lucid \w bundled Apache 2.2.14 and Mysql 5.1.41



 Description   

config/doctrine/schema.yml:
JobeetCategory:
actAs:
Timestampable: ~
I18n:
fields: [name]
columns:
id:
type: integer(4)
primary: true
autoincrement: true
num:
type: integer(4)
name:
type: string(255)
notnull: true

lib/form/doctrine/JobeetCategoryForm.class.php:
class JobeetCategoryForm extends BaseJobeetCategoryForm
{
public function configure()

{ $this->embedI18n(array('nl')); }

}

then running:
./symfony doctrine:generate-module --non-verbose-templates --with-show backend category JobeetCategory

surfing to:
backend_dev.php/category/new

everything looks fine but as soon as I post valid data i get the following error:
500 | Internal Server Error | Doctrine_Connection_Mysql_Exception
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1-nl' for key 'PRIMARY'

And in my sql log i see it tries to execute the following (and fails):
START TRANSACTION
INSERT INTO `jobeet_category` (`created_at`, `updated_at`) VALUES ('2005-01-01 00:00:00', '2005-01-01 00:01:00')
INSERT INTO `jobeet_category_translation` (`id`, `lang`, `name`) VALUES ('1', 'nl', '2378')
INSERT INTO `jobeet_category_translation` (`id`, `lang`) VALUES ('1', 'nl_NL')
ROLLBACK

Obviously this third insert is not ok, but why is doctrine running it?

I tried the Jobeet demo locally to see if I get the same issues with editing the I18n categories in the backend, but that all runs fine..

I tried a apps/backend/config/settings.yml with:

  1. i18n
    i18n: true
    default_culture: nl
    standard_helpers: [Partial, I18N]

and I also tried it commenting it all out. Still doesn't work.

I really don't know why Doctrine runs this third insert and why it is using the incorrect "nl_NL" instead of "nl".



 Comments   
Comment by Jonathan Pasquier [ 14/Oct/10 ]

Hi,

I had the same problem, and was able to solve it setting the culture of the user.

In my case, I had two languages: "ca" and "es" (catalan and spanish), and my default culture defined in settings.yml was "ca_ES"

Every time I tried to save a symfony form with embeded translation forms, I got an error similar to the following one:
Integrity constraint violation: 1062 Duplicate entry '3-ca' for key 'PRIMARY'

Basically, symfony or Doctrine, was trying to do 3 inserts: one with the "ca" language, one with the "es" language and one with the "ca_ES" language!

Here is the symfony log:

Oct 13 14:38:46 symfony [info] {Doctrine_Connection_Mysql} exec : SET NAMES 'UTF8' - ()
Oct 13 14:38:46 symfony [info] {Doctrine_Connection_Statement} execute : SELECT COUNT(*) AS num_results FROM client c WHERE c.id = ? - (1)
Oct 13 14:38:46 symfony [info] {Doctrine_Connection_Statement} execute : INSERT INTO campanya (client_id, idiomes, created_at, updated_at) VALUES (?, ?, ?, ?) - (1, a:1:{i:0;s:2:"ca";}, 2010-10-13 14:38:46, 2010-10-13 14:38:46)
Oct 13 14:38:46 symfony [info] {Doctrine_Connection_Statement} execute : SELECT c.id AS c__id, c.lang AS c__lang, c.slug AS c__slug FROM campanya_translation c WHERE (c.slug LIKE ? AND c.lang = ? AND c.nom = ?) - (aixo-es-una-nova-campanya-en-catala%, ca, Això és una nova campanya, en català)
Oct 13 14:38:46 symfony [info] {Doctrine_Connection_Statement} execute : INSERT INTO campanya_translation (id, lang, nom, descripcio, slug) VALUES (?, ?, ?, ?, ?) - (3, ca, Això és una nova campanya, en català, Lorem ipsum dolor...
Hic et nunc!, aixo-es-una-nova-campanya-en-catala)
Oct 13 14:38:46 symfony [info] {Doctrine_Connection_Statement} execute : SELECT c.id AS c__id, c.lang AS c__lang, c.slug AS c__slug FROM campanya_translation c WHERE (c.slug LIKE ? AND c.lang = ? AND c.nom = ?) - (%, es, )
Oct 13 14:38:46 symfony [info] {Doctrine_Connection_Statement} execute : INSERT INTO campanya_translation (id, lang, nom, descripcio, slug) VALUES (?, ?, ?, ?, ?) - (3, es, , , )
Oct 13 14:38:46 symfony [info] {Doctrine_Connection_Statement} execute : SELECT c.id AS c__id, c.lang AS c__lang, c.slug AS c__slug FROM campanya_translation c WHERE (c.slug LIKE ? AND c.lang = ? AND c.nom IS NULL) - (%, ca_ES)
Oct 13 14:38:46 symfony [info] {Doctrine_Connection_Statement} execute : INSERT INTO campanya_translation (id, lang, slug) VALUES (?, ?, ?) - (3, ca_ES, )
Oct 13 14:38:46 symfony [err] {Doctrine_Connection_Mysql_Exception} SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '3-ca' for key 'PRIMARY'

Finally, I was able to solve it doing a:
$this->getUser()->setCulture('ca');
when users log into my application.

I'm using symfony 1.4.9





[DC-728] Updating slug in I18N behaviour yields non-unique slug Created: 11/Jun/10  Updated: 05/Oct/10

Status: Open
Project: Doctrine 1
Component/s: I18n, Sluggable
Affects Version/s: 1.2.0, 1.2.1, 1.2.2
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Florian Aschenbrenner Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 5
Labels: None
Environment:

Symfony 1.4.5
Doctrine ORM



 Description   

There seems to be a bug in the way, doctrine tries to find a unique slug for a table that is I18N-enabled and has a slug in it.

Following example:

Problem:
  actAs:
    I18n:
      fields: [name]
      actAs:
        Sluggable: { fields: [name], uniqueBy: [lang, name], canUpdate: true }
  columns:
    name: { type: string(255), notnull: true }

Now, if we insert a new entry, the slug get's created as expected. If we now insert another entry that would yield the same slug, the slug is made unique by adding the postfix as expected - all well so far.

Now, if we try to update the entry with the slug with the postfix, what i think is an error happens (Excerpt from Sluggable.php, lib/Doctrine/Template/Listener/Sluggable.php):

 
public function getUniqueSlug($record, $slugFromFields)
...
if ($record->exists()) {
            $identifier = $record->identifier();
            $whereString .= ' AND r.' . implode(' != ? AND r.', $table->getIdentifierColumnNames()) . ' != ?';
            $whereParams = array_merge($whereParams, array_values($identifier));
        }

        foreach ($this->_options['uniqueBy'] as $uniqueBy) {
            if (is_null($record->$uniqueBy)) {
                $whereString .= ' AND r.'.$uniqueBy.' IS NULL';
            } else {
                $whereString .= ' AND r.'.$uniqueBy.' = ?';
                $value = $record->$uniqueBy;
                if ($value instanceof Doctrine_Record) {
                    $value = current((array) $value->identifier());
                }
                $whereParams[] = $value;
            }
        }
...

So, the $record->exists() check evaluates to true and $table->getIdentifierColumnNames() yields the fields id and lang, so the whereString is something like

 
AND r.id != ? AND r.lang != ?

Now for the problematic part:
uniqueBy is lang and name; so the code adds to the whereString:

 
AND r.lang = ? AND r.name = ?

So the resulting whereString has something like

 
r.lang != ? AND r.lang = ?

which will never yield a result in my eyes, thus, the postfix is never incremented and the slug defaults to the the slug of name without postfix.



 Comments   
Comment by Rodrigo Borrego Bernabé [ 24/Jun/10 ]

Hi,

We've also found this problem and make a temporal workaround. But maybe our workaround can give someone an idea on how to fix the bug so I'm pasting the changed code here

In file sfDoctrinePlugin\lib\vendor\doctrine\Doctrine\Template\Listener\Sluggable.php (getUniqueSlug method)

Replace

if ($record->exists()) {
  $identifier = $record->identifier();
  $whereString .= ' AND r.' . implode(' != ? AND r.', $table->getIdentifierColumnNames()) . ' != ?';
  $whereParams = array_merge($whereParams, array_values($identifier));
}

With

if ($record->exists()) {
  $identifier = $record->identifier();
  $commonFields = array_uintersect($table->getIdentifierColumnNames(), $this->_options['uniqueBy'], "strcasecmp");
  foreach ($commonFields as $key => $value)
    unset ($identifier[$value]);
  
  $whereFields = array_diff($table->getIdentifierColumnNames(), $this->_options['uniqueBy']);
  $whereString .= ' AND r.' . implode(' != ? AND r.', $whereFields) . ' != ?';
  $whereParams = array_merge($whereParams, array_values($identifier));
}
Comment by Christian Seaman [ 05/Oct/10 ]

Rodrigo, I think the solution is simpler than you might expect...

The problem is that it is doing an AND where it should be doing an OR to find records other than the current one.

So, you just need to replace this part of Sluggable::getUniqueSlug():

Sluggable::getUniqueSlug()
...
        if ($record->exists()) {
            $identifier = $record->identifier();
            $whereString .= ' AND r.' . implode(' != ? AND r.', $table->getIdentifierColumnNames()) . ' != ?';
            $whereParams = array_merge($whereParams, array_values($identifier));
        }
...

With this code (the 3rd line has extra brackets and OR instead of AND):

Sluggable::getUniqueSlug() (modified)
        if ($record->exists()) {
            $identifier = $record->identifier();
            $whereString .= ' AND (r.' . implode(' != ? OR r.', $table->getIdentifierColumnNames()) . ' != ?)';
            $whereParams = array_merge($whereParams, array_values($identifier));
        }

In more detail, the WHERE clause being built up is saying:
"find me records WHERE (the slug begins with the same string) AND (it's not the same record) AND (the other key uniqueBy values are the same)"

However, to check that it's not the same record you just need one of the key values to be different (not all of them) so the check should be something like:

... AND (p.id != '2' OR p.lang != 'en') ...

instead of:

... AND p.id != '2' AND p.lang != 'en' ...

The modification to the code as stated above generates queries that look like this, which I'm pretty sure is correct:

... WHERE (p.url LIKE 'foo%' AND (p.id != '2' OR p.lang != 'en') AND p.lang = 'en' AND p.other_uniqueby_field = '1')

C





[DC-450] ORACLE: The generate DQL with i18n behavior doesn't correct Created: 25/Jan/10  Updated: 18/Mar/10

Status: Open
Project: Doctrine 1
Component/s: I18n
Affects Version/s: 1.2.1
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Bertrand Zuchuat Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None

Attachments: File DC450TestCase.php    

 Description   

My schema:

---
Country:
  tableName:          country
  actAs:
    SoftDelete:       ~
    Timestampable:    ~
    I18n:
      fields:         [name]
      className:      %CLASS%I18n
      tableName:      %TABLE%_i18n
      length:         5
  columns:
    id:
      type:           integer(3)
      primary:        true
      unsigned:       true
      sequence:       country
    created_at:
      type:           timestamp
    updated_at:
      type:           timestamp
    enabled_at:
      type:           timestamp
      notnull:        true
    disabled_at:
      type:           timestamp
    iso_code:
      type:           string(2)
    marc_code:
      type:           string(3)
    name:
      type:           string(255)
      notnull:        true

DQL query:

 
$country = Doctrine::getTable('Country')->findOneByMarcCode('sz');

Error:

 
ORA-00904: "C"."NAME": invalid identifier : SELECT a.* FROM ( SELECT c.id AS c__id, c.created_at AS c__created_at, c.updated_at AS c__updated_at, c.enabled_at AS 
c__enabled_at, c.disabled_at AS c__disabled_at, c.iso_code AS c__iso_code, c.marc_code AS c__marc_code, c.name AS c__name, c.deleted_at AS c__deleted_at FROM
common.country c WHERE (c.marc_code = :oci_b_var_1) ) a WHERE ROWNUM <= 1 

In this line, i show the field "name", but this field is in table translation. The DQL above is very complicated for only simple request. Why ?

Thank's

Bertrand



 Comments   
Comment by Bertrand Zuchuat [ 18/Mar/10 ]

I don't have a real connection on Oracle Server. This test doesn't return the error above.

Please test on real connection.

Thanks





[DC-443] Incorrect insert order in i18n entities Created: 22/Jan/10  Updated: 22/Jan/10

Status: Open
Project: Doctrine 1
Component/s: I18n, Relations
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Rodrigo Borrego Bernabé Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Linux (2.6.21 kernel)
Apache/2.2.6
PHP 5.2.6
symfony version 1.4.1
doctrine 1.2


Attachments: File i18nrelation_problem.tgz    

 Description   

If the schema has an entity MyMain with all its fields i18n and an entity MySecondary related to MyMain and you try to create a new MySecondary item using Symfony forms you get an error.

I think the error is doctrine and in i18n because if you remove a field from the i18n behavior (fields: [a,b,c,d], for example) all works ok.
I've included a symfony project to help developpers replicate the error.

My Schema

 
MyMain:
  actAs:
    I18n:
      fields: [a,b,c,d, e]
  columns:
    a:  { type: string(255), notnull: true }
    b:  { type: string(255), notnull: true }
    c:  string
    d:  string
    e:  string

MySecondary:
  columns:
    my_main_id:  integer
    a:        string(255)
    b:        string(255)
  relations:
    MyMain:
      local: my_main_id
      foreign: id
      foreignType: one
      cascade: [delete]

And the form code

class MyMainForm extends BaseMyMainForm
{
  public function configure()
  {
    $this->embedI18n(array('en', 'es'));
  }
}

class MySecondaryForm extends BaseMySecondaryForm
{
  public function configure()
  {
    $this->widgetSchema['my_main_id'] = new sfWidgetFormInputHidden();
    $this->embedRelation('MyMain as main_subform');
  }
}

And last the queries (and its order when you get the error)

INSERT INTO my_secondary (my_main_id, a, b) VALUES (?, ?, ?) - (, my_secondary[a], my_secondary[b])
INSERT INTO my_main_translation (id, lang, a, b, c, d, e) VALUES (?, ?, ?, ?, ?, ?, ?) - 
  (, en, my_secondary[main_subform][en][a], my_secondary[main_subform][en][b], my_secondary[main_subform][en][c], 
   my_secondary[main_subform][en][d], my_secondary[main_subform][en][e])
Error Doctrine_Connection_Mysql_Exception	SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'id' cannot be null 





[DC-438] Nesting Taggable and I18N Created: 19/Jan/10  Updated: 19/Jan/10

Status: Open
Project: Doctrine 1
Component/s: Extensions, I18n
Affects Version/s: 1.2.1
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Sorin Neacsu Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 1
Labels: None
Environment:

PHP 5.2.6, MySQL 5.0.75, Symfony 1.3.1



 Description   

The Taggable extension doesnt work correctly when nested under I18N.
The page_translation_taggable_tag table appears to be correctly created, it has 3 columns: id, lang, tag_id
But when you save a tag like this
$page->Translation['en']->setTags('tag 1, tag2');
the lang column in page_translation_taggable_tag is empty
and this doesnt work either:
$page->setTags('tag 1, tag2');

Schema is this:
Page:
actAs:
I18n:
fields: [title, contents]
actAs:
Taggable: ~
columns:
title:

{type: string(255), notnull: true}

contents: clob






[DC-412] Error defining "unique" constraint in a translated (i18n) column Created: 09/Jan/10  Updated: 10/Jan/10

Status: Open
Project: Doctrine 1
Component/s: I18n
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: David Marín Carreño Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 1
Labels: None


 Description   

Let's suppose we have a class "Element" with columns "name" and "description".

We want to set an "unique" constraint in column "name", and set the I18n behavior to columns name and description.

In the generated translation table "element_translation", doctrine sets an unique constraint in the column "name". This is an error, as various languages could translate that string in the same way. I think that the "unique" constraint should be set to the combination of columns "name" and "lang", so the restriction applies for a given language.






[DC-372] I18n record generator assumes relation alias is the table name Created: 20/Dec/09  Updated: 20/Dec/09

Status: Open
Project: Doctrine 1
Component/s: I18n
Affects Version/s: 1.2.1
Fix Version/s: None

Type: Bug Priority: Major
Reporter: thibault duplessis Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 1
Labels: None
Environment:

latest symfony 1.4 SVN.



 Description   

In Doctrine/I18n.php, method setTableDefinition, line 108:

        foreach($relations as $table => $relation) {

But the $relations array key is not a table name, but a relation alias.

So currently the generator assumes the relation alias IS the table name.
When it's not true, the I18n table definition fails.






[DC-373] Relating to Translation table (generated by Doctrine_I18n) doesn't work correctly after resetting connection Created: 20/Dec/09  Updated: 19/Dec/14

Status: Open
Project: Doctrine 1
Component/s: Connection, I18n
Affects Version/s: 1.2.1, 1.2.2, 1.2.3
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Kousuke Ebihara Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 2
Labels: None
Environment:

PHP 5.2.11 (with Suhosin-Patch 0.9.7)
PHP 5.3.6


Attachments: File DC373TestCase.php    

 Description   

Relating to Translation table (generated by Doctrine_I18n) doesn't work correctly after resetting connection.

First, I defined the following schema.yml::

 
  Example:
    actAs:
      I18n:
        fields: [title]
    columns:
        title: string(128)

Next, I prepared the following fixture file::

 
  Example:
    Example_1:
      Translation:
        en:
          title: "Title"
        ja:
          title: "題名"

Next, I run "build-all-reload" task. The table was created and data was loaded.

And I write the following code::

 
  Doctrine_Core::loadModels('models');
  $example = Doctrine_Core::getTable('Example')->find(1);
  
  var_dump(
    $example->Translation['en']->title,
    $example->Translation['ja']->title
  );
  
  Doctrine_Manager::resetInstance();
  Doctrine_Manager::getInstance()->openConnection(DSN, 'doctrine');
  
  $example2 = Doctrine_Core::getTable('Example')->find(1);
  var_dump(
    $example2->Translation['en']->title,
    $example2->Translation['ja']->title
  );

I try executing my code, but I got the following error::

  string(5) "Title"
  string(6) "題名"
  
  Doctrine_Connection_Mysql_Exception: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'e.title' in 'field list' in /path/to/doctrine/Doctrine/Connection.php on line 1082
  
  Call Stack:
      0.0055      65352   1. {main}() /path/to/my/code/test.php:0
      0.2776    5873388   2. Doctrine_Table->find() /path/to/my/code/test.php:52
      0.2793    5881152   3. Doctrine_Query->fetchOne() /path/to/doctrine/Doctrine/Table.php:1611
      0.2793    5881296   4. Doctrine_Query_Abstract->execute() /path/to/doctrine/Doctrine/Query.php:281
      0.2793    5881892   5. Doctrine_Query_Abstract->_execute() /path/to/doctrine/Doctrine/Query/Abstract.php:1026
      0.3127    5890712   6. Doctrine_Connection->execute() /path/to/doctrine/Doctrine/Query/Abstract.php:976
      0.3164    5892632   7. Doctrine_Connection_Statement->execute() /path/to/doctrine/Doctrine/Connection.php:1006
      0.3181    5907408   8. Doctrine_Connection->rethrowException() /path/to/doctrine/Doctrine/Connection/Statement.php:269


 Comments   
Comment by Arnaud Charlier [ 02/Nov/10 ]

Good Morning,

First, thanks a lot for your work on Doctrine. It's a real great tool we love to use.

Currently in one of our big application we have exactly the same issue.
It seems when we close the connection, the reference with the objectTranslation is lost.
Re-open the connection seems not able to reinstantiate this Translation link to the objectTranslation.

Currently we have no solution, but we are still investigating this.

I'm available to go deep in the code with you, but any Doctrine Team help will be really nice.

Thanks to let me know as soon as possible.

Arnaud

Comment by Joe Siponen [ 27/May/11 ]

I've just now battled with the very same problem in Doctrine 1.2 (the version bundled with symfony 1.4) and the problem seems to be caused by the fact that Doctrine_Record_Generator simply isn't written such that it is able to reinitialize generators for unloaded table instances after a connection is closed. This problem also manifests itself after a table has been loaded in a connection and one tries retrieve a table again after Doctrine_Connection->evictTables() has been called. This makes it impossible to to open more than one connection at a time in a request/script when using behaviors that dynamically modify table instances (such as the i18n behavior).

Doctrine_Record_Generator determines if it needs to run its initialization methods simply by checking if the to-be generated class, as defined by the className option, exists using a class_exists call. This means that the first time this method is called the initialization happens but for every subsequent call no initialization is made. Now, in the i18m behavior, the important initialization happens in its setTableDefinition method in which it removes any of the translated fields from the table instance that is been setup and redefines them as relations on the to-be-created Translation class. It then finishes off by dynamically declaring the new class for the translation record using its generateClassFromTable method.

Thus, the first time everything goes smoothly and the i18n generator's setTableDefinition is called and the table instance is properly initialized. Everything will now work as expected while the current connection is open since the connection instance keeps the i18n modified table instances alive and well for callers.

But, when the current connection is closed the i18n modified table instances it holds are also removed (goes out of scope). Then, when a new connection is opened, this new connection will start without having any table instances. This means that the next time one asks the new connection for a table instance of the same class with the i18n behavior the i18n behaviors will fail to initialize because the generator at this time believes its class has actually been initialized which, in turn, means that the table using the i18n behavior isn't properly initialized. No initialization means that this table will now include the non-existant i18n fields in the select part of its queries (those are in the translation table) causing those queries to fail miserably.

I believe this could be fixed by adding a static attribute to Doctrine_Record_Generator that tracks the spl_object_hash of the underlying dbh instance variable of the doctrine connection of the table parameter. If the hash is the same the next time that the initialize method is called the generator can decide not to reinitialize itself but if it detects that the hash of the current connection is different then that is definitely a clue to the generator that it needs to reinitialize itself (i.e. run all of the initialization methods but generateClassFromTable which should't be called more than once).

Maybe do it like this perhaps:

 
abstract class Doctrine_Record_Generator extends Doctrine_Record_Abstract
{
  public function initialize(Doctrine_Table $table)
  {
    /* ... */ 
  
    $currentConnectionHash = spl_object_hash($table->getConnection()->getDbh());
    
    //Next part is called if this is the first connection made or if this is a new open connection with new table instances
    if ($currentConnectionHash != self::$lastConnectionHash)
    {
      self::$lastConnectionHash = $currentConnectionHash;
      
      $this->buildTable();

      $fk = $this->buildForeignKeys($this->_options['table']);

      $this->_table->setColumns($fk);

      $this->buildRelation();

      $this->setTableDefinition();
      $this->setUp();
      
      if ($this->_options['generateFiles'] === false && class_exists($this->_options['className'])) {
        $this->generateClassFromTable($this->_table); //Don't generate the class more than once ever
      }
      
      $this->buildChildDefinitions();

      $this->_table->initIdentifier();
    }
  }
}
Comment by Joe Siponen [ 16/Jun/11 ]

Failing test case attached

Comment by Kousuke Ebihara [ 08/Jun/12 ]

Good job, Joe Siponen! Thanks for your nice patch!

I can't understand why the Doctrine team discontinued maintenance of Doctrine 1 without any fixes for some serious issues like this problem...

Joe, would you send your patch by pull-request in GitHub? They might notice this problem and try to fix in official repository by your request. If you cannnot, I will do it as your proxy. (Of course I'm going to describe your credit)

Comment by Kousuke Ebihara [ 11/Sep/12 ]

I've tested Joe Siponen's patch, it would be good in a situation of single connection, but it doesn't work in multiple connections.

So I modified your patch to fit my needs. I'm testing my arranged patch and I want to publish it ASAP...

Comment by Baptiste SIMON - Libre Informatique [ 15/Dec/14 ]

Hi guys,

I found a workaround for this bug on multiple DB connections :
In my *-schema.yml I have defined my i18n table as :

(...)
actAs:
I18n:
fields: [xxx, yyy, zzz]
generateFiles: true
generatePath: <?php echo sfConfig::get('sf_lib_dir'); ?>/model/doctrine/i18n
(...)

(notice the generateFiles & generatePath...)

This (alone) seems to solve my issue. I'll give more feed back if there is any.
FEEDBACK: do not work with inheritated behaviors... so it's not correct for our needs.

sources: http://forum.symfony-project.org/viewtopic.php?t=24071

Comment by Baptiste SIMON - Libre Informatique [ 15/Dec/14 ]

eventually, for a portable solution (web), you can use this path :

(...)
generatePath: ../<?php echo str_replace(sfConfig::get('sf_root_dir').'/', '', sfConfig::get('sf_lib_dir')) ?>/model/doctrine/i18n
(...)

this is a trick for file replication between servers that have different DOCUMENT_ROOT path.

Comment by Baptiste SIMON - Libre Informatique [ 19/Dec/14 ]

ok sorry for the multiple posts... I maybe have found a smart solution by patching Doctrine/Record/Generator.php that way :

Index: Doctrine/Record/Generator.php
===================================================================
— Doctrine/Record/Generator.php (révision 4690)
+++ Doctrine/Record/Generator.php (copie de travail)
@@ -163,7 +163,7 @@
// check that class doesn't exist (otherwise we cannot create it)
if ($this->_options['generateFiles'] === false && class_exists($this->_options['className']))

{ $this->_table = Doctrine_Core::getTable($this->_options['className']); - return false; + //return false; }

$this->buildTable();
@@ -461,10 +461,10 @@
} else

{ throw new Doctrine_Record_Exception('If you wish to generate files then you must specify the path to generate the files in.'); }
  • } else { + }

    elseif ( !class_exists($definition['className']) )

    { $def = $builder->buildDefinition($definition); eval($def); }

    }

This implicates multiple rebuilding of the same class, but at least, it works... without any modifications in the schema.

Comment by Baptiste SIMON - Libre Informatique [ 19/Dec/14 ]

I found another failing case, very very isolated... And I improved the patch.
To avoid some kind of flooding here, here is the reference of the latest solution :

http://www.e-glop.net/main/Rendre_Doctrine1_multi-connexions_fonctionnel_avec_ses_diff%C3%A9rents_Behaviors





[DC-1029] Extensions of Doctrine_Template_I18n incompatible with Doctrine_Import Created: 18/Aug/11  Updated: 17/Apr/14

Status: Open
Project: Doctrine 1
Component/s: Data Fixtures, I18n, Import/Export
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Trivial
Reporter: Pierrot Evrard Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Windows 7, XAMPP 1.7.4 with APC and Curl, symfony 1.4.8


Attachments: Text File DC-1029.patch    

 Description   

Extending Doctrine_Template_I18n class make Doctrine_Import on YAML data with translation fails...

Why ? Just because of this line :

Doctrine_Import.php, line 135 :
if ($table->hasRelation($key) && is_array($value) && ! $table->hasTemplate('Doctrine_Template_I18n')) {

In fact, having a template named "Doctrine_Template_I18n" is not strong enough to be sure that the current object has an I18n behavior.

The bug is very simple to reproduce :

1. Get a classic I18n fixtures like :

Article:
Translation:
en:
title: Lorem Ipsum

2. Then make a simple extension of the I18n template (do not do anything else but extends the Doctrine_Template_I18n class) :

class My_Doctrine_Template_I18n extends Doctrine_Template_I18n {}

3. Load the extension, assign it to your model and try to import your fixtures again. It will not work anymore.

Thanks



 Comments   
Comment by Pierrot Evrard [ 18/Aug/11 ]

See this patch where to check if the table has the I18n plugin, I check if one of the templates has a getI18n() method.

This is probably not strong enough but it can do the job until you find a better solution.

Thanks

Comment by Pierrot Evrard [ 18/Aug/11 ]

Another possibility to check that templates are I18n template, will be to create an Doctrine_I18n_Interface. Also, every template that include this interface can be considered as I18n templates.

What do you think about that ?

NB: May the interface can define the method getI18n() to be declared...





Generated at Mon Dec 22 17:10:39 UTC 2014 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.