2013-03-26 17 views
5

Właśnie zauważyłem, że propel konwertuje wartości liczbowe na ciągi w generowanych metodach ustawiania. Mój problem polega na tym, że ponieważ używam niemieckiego ustawienia narodowego, wartości zmiennoprzecinkowe są wstawiane za pomocą przecinka zamiast kropki. Na przykład: "3.5" daje ciąg "3,5". Używam PostgreSQL, który oczywiście oczekuje 3.5.Dlaczego Propel przekształca właściwość float na ciąg?

Informacje o wersji: Jeśli jest to istotne, używam: PHP 5.3.9, Propel 1.6 z Symfony 2.2.

Szczegóły:

Definicja tabela wygląda następująco:

<table name="account_entry"> 
    ... 
    <column name="amount" type="decimal" size="12" scale="2" required="true" /> 
    ... 
</table> 

Wygenerowany setAmount() metoda wygląda następująco:

public function setAmount($v) 
{ 
    if ($v !== null && is_numeric($v)) { 
     $v = (string) $v; 
    } 

    if ($this->amount !== $v) { 
     $this->amount = $v; 
     $this->modifiedColumns[] = AccountEntryPeer::AMOUNT; 
    } 


    return $this; 
} // setAmount() 

Zapisywanie wyników obiekt w PostgreSQL błąd:

Invalid text representation: 7 ERROR: invalid input syntax for type numeric: "3,5" 

Zajęło mi trochę czasu znalezienie miejsca, w którym dochodzi do konwersji. Jak widać, wartość zmiennoprzecinkowa jest przesyłana do łańcucha w setAmount(). Do tej pory nigdy nie zauważyłem, że rzutowanie wartości zmiennoprzecinkowej na łańcuch znaków skutkuje łańcuchem zawierającym separator dziesiętny specyficzny dla ustawień narodowych.

Zastanawiam się, dlaczego propel w pierwszej kolejności konwertuje wartość zmiennopozycyjną na ciąg? Czy jest jakiś sposób obejścia tego problemu?

Jedyne obejście wymyśliłem jest naprawdę brzydki i irytujący:

setlocale(LC_ALL, 'en_US'); 
$ae->setAmount(3.5); 
setlocale(LC_ALL, 'de_DE'); 
+0

Wygląda na to, że jest to [domyślne * zachowanie *] (https://github.com/propelorm/Propel/blob/master/generator/lib/builder/om/PHP5ObjectBuilder.php#L1844-1873) do obsługi kolumna. Ale zgodnie ze sposobem generowania kodu SQL (np. Wstawiania) [wydaje się] (https://github.com/propelorm/Propel/blob/master/generator/lib/builder/sql/DataSQLBuilder.php#L172 -180), że powinien zostać rzucony * ponownie *, aby dopasować rodzimy typ kolumny. Możesz sprawdzić [problem na Github] (https://github.com/propelorm/Propel/issues) i/lub złożyć jeden – j0k

+0

Dziękuję za twoje badania. Wysłałem pytanie na listę dyskusyjną z propelem. Chcę uniknąć tworzenia raportów o błędach, jeśli to nie jest błąd. – Leif

Odpowiedz

5

Problemem jest to, że Propel konwertuje pole PHP, który odnosi się do tej kolumny do natywnego typu PHP w seter (jak @ J0K wzmianki), ale jeśli spojrzysz nieco głębiej, zobaczysz problem. W klasie pomocniczej PropelTypes.php, w linii 76 widać, że natywny typ PHP dla "dziesiętnego" jest wymieniony jako "ciąg".

Należy porównać to z natywnym typem "float", który jest wymieniony jako "double". Nie jestem pewien, czy jest to celowe, czy nie, ale w każdym razie problem można rozwiązać, po prostu przełączając kolumnę na type="float" lub type="double".

Propel powinien przekonwertować go na dowolny typ wymagany przez DBMS.

+0

Dzięki! Zmiana typu z dziesiętnego na podwójny rzeczywiście rozwiązuje mój problem. Nadal uważam, że jest to rozwiązanie tymczasowe, ponieważ PostgreSQL używa teraz podwójnego typu, a nie dziesiętnego (x, y). Ale to jest w porządku dla mojej sprawy. – Leif

+0

Cieszę się, że działało. Naprawdę nie jestem pewien, dlaczego ludzie z rodziny Propel domyślnie przypisali typ natywny do "stringów", ale może to ma sens w przypadku niektórych DBMS. – jakerella

+3

Dzieje się tak dlatego, że pole DECIMAL w bazach danych jest precyzyjne, podczas gdy natywne sterowanie zmiennoprzecinkowe na CPU nie jest. W ten sposób Propel odtwarza go bezpiecznie, zwracając dokładną wartość w ciągu znaków i pozwalając ci martwić się arytmetyką i przechowywaniem. Zobacz f.e. [link] (http://msdn.microsoft.com/en-us/library/c151dt3s%28v=vs.80%29.aspx) – Noora