Widziałem to pytanie powtórzone kilka razy w Stack Overflow, ale żadne z nich w wystarczającym stopniu nie zbadało problemu (lub przynajmniej w sposób, który jest dla mnie pomocny)
Problem polega na tym, że zapytanie DB powinno zwracać w PHP typy danych w postaci liczb całkowitych dla kolumn całkowitych. Zamiast tego kwerenda zwraca każdą kolumnę jako typ ciągu.
Zapewniłem, że „PDO :: ATTR_STRINGIFY_FETCHES” jest fałszywe, aby upewnić się, że wyniki nie są rzutowane na łańcuch.
Odpowiedzi, które widziałem:
- Nie da się tego zrobić
- Nie, to działa na Mac OS X z zainstalowanym PHP / MySQL
- Wpisz rzutuj wszystkie wartości w kodzie
- Nie, nie będę tego robić
- Nie martw się, PHP jest luźno wpisane
- Moje dane są wyprowadzane w formacie JSON i są używane przez wiele innych usług, niektóre wymagają danych w odpowiednim formacie
Z moich badań wynika, że jest to problem dotyczący implementacji sterownika.
Wiele źródeł twierdzi, że natywny sterownik MySQL nie obsługuje zwracania typów liczbowych. Nie wydaje się to prawdą, ponieważ działa w systemie Mac OS X. Chyba że mają na myśli stwierdzenie, że „natywny sterownik MySQL w systemie Linux nie obsługuje tej funkcji”.
Oznacza to, że jest coś szczególnego w sterowniku / środowisku, które zainstalowałem w systemie Mac OS X. Próbowałem zidentyfikować różnice, aby zastosować poprawkę, ale jestem ograniczona wiedzą, jak to sprawdzić.
Różnice:
- PHP na OS X zostało skompilowane i zainstalowane przez Home Brew
- PHP na Ubuntu zostało zainstalowane przez „apt-get install php5-dev”
- PHP na OS X łączy się z serwerem MySQL również działającym na OS X.
- Wersja serwera: 5.1.71-log Dystrybucja źródła
- PHP na Ubuntu łączy się z bazą danych w chmurze Rackspace
- Wersja serwera: 5.1.66-0 + squeeze1 (Debian)
Środowisko Ubuntu
- Wersja: 10.04.1
- PHP 5.4.21-1 + debphp.org ~ lucid + 1 (cli) (zbudowano: 21 października 2013 08:14:37)
php -i
pdo_mysql
Sterownik PDO dla MySQL => włączona wersja Client API => 5.1.72
Środowisko Mac OS X
- 10.7.5
- PHP 5.4.16 (cli) (zbudowano: 22 sierpnia 2013 09:05:58)
php -i
pdo_mysql
Sterownik PDO dla MySQL => włączona wersja Client API => mysqlnd 5.0.10 - 20111026 - $ Id: e707c415db32080b3752b232487a435ee0372157 $
Używane flagi PDO
PDO::ATTR_CASE => PDO::CASE_NATURAL,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
PDO::ATTR_STRINGIFY_FETCHES => false,
PDO::ATTR_EMULATE_PREPARES => false,
Będziemy wdzięczni za wszelką pomoc i wiedzę :) Na pewno wrócę tutaj, jeśli znajdę odpowiedź.
Odpowiedzi:
Rozwiązaniem jest upewnienie się, że używasz sterownika mysqlnd dla php.
Skąd wiesz, że nie używasz mysqlnd?
Podczas oglądania
php -i
, nie będzie bez wzmianki o „mysqlnd”.pdo_mysql
Odcinek będzie miał coś takiego:pdo_mysql PDO Driver for MySQL => enabled Client API version => 5.1.72
Jak to zainstalować?
Większość przewodników instalacyjne dla L / A / M / P sugerują
apt-get install php5-mysql
jednak natywny sterownik MySQL jest instalowany przez inny pakiet:php5-mysqlnd
. Okazało się, że było to dostępne z ppa: ondrej / php5-oldstable .Aby przełączyć się na nowy sterownik (w systemie Ubuntu):
apt-get remove php5-mysql
apt-get install php5-mysqlnd
service apache2 restart
Jak mogę sprawdzić, czy sterownik jest używany?
Teraz
php -i
wpdo_mysql
sekcji wyraźnie wymienimy „mysqlnd” :pdo_mysql PDO Driver for MySQL => enabled Client API version => mysqlnd 5.0.10 - 20111026 - $Id: e707c415db32080b3752b232487a435ee0372157 $
Ustawienia PDO
Upewnij się, że
PDO::ATTR_EMULATE_PREPARES
jestfalse
(sprawdź ustawienia domyślne lub ustaw je):$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Upewnij się, że
PDO::ATTR_STRINGIFY_FETCHES
jestfalse
(sprawdź ustawienia domyślne lub ustaw je):$pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
Zwracane wartości
† BIGINT o wartości większej niż 64-bitowa liczba int ze znakiem (9223372036854775807) zostanie zwrócona jako ciąg (lub 32 bity w systemie 32-bitowym)
object(stdClass)[915] public 'integer_col' => int 1 public 'double_col' => float 1.55 public 'float_col' => float 1.5 public 'decimal_col' => string '1.20' (length=4) public 'bigint_col' => string '18446744073709551615' (length=20)
źródło
0.30
jak"0.30"
zamiast0.3
. Do tego używane sąPDO::ATTR_EMULATE_PREPARES
użyć nazwanego parametru więcej niż razTa zaakceptowana odpowiedź działa i wydaje się być najpopularniejszą odpowiedzią w Google na to pytanie. Mój problem polega na tym, że muszę wdrożyć aplikację w wielu środowiskach i nie zawsze mam możliwość zainstalowania odpowiedniego sterownika, a ponadto potrzebuję liczb dziesiętnych, aby były liczbami, a nie ciągami. Dlatego stworzyłem procedurę wpisywania wielkości liter przed kodowaniem JSON, którą można łatwo zmodyfikować. To trochę jak zbombardowanie go z orbity.
Najpierw użyj polecenia „pokaż kolumny z”, aby pobrać kolumny z tabeli. mysql query „SHOW COLUMNS FROM table like 'colmunname'”: pytania
$query = 'SHOW COLUMNS FROM ' . $table; //run with mysqli or PDO
Następnie przenieś typy do tablicy indeksowanej według nazwy kolumny, aby ułatwić iterację. Zakłada, że zestaw wyników z pokazu kolumn znajduje się w zmiennej o nazwie $ columns_from_table. http://php.net/manual/en/function.array-column.php
$column_types = array_column( $columns_from_table, 'Type', 'Field');
Następnie chcemy usunąć nawias z typu, który będzie czymś w rodzaju varchar (32) lub decimal (14,6)
foreach( $column_types as $col=>$type ) { $len = strpos( $type, '(' ); if( $len !== false ) { $column_types[ $col ] = substr( $type, 0, $len ); } }
Teraz mamy skojarzoną tablicę z nazwą kolumny jako indeksem i sformatowanym typem jako wartością, na przykład:
Array ( [id] => int [name] => varchar [balance] => decimal ... )
Teraz, gdy dokonasz wyboru z tabeli, możesz iterować wyniki i rzutować wartość na odpowiedni typ:
foreach( $results as $index=>$row ) { foreach( $row as $col=>$value ) { switch( $column_types[$col] ) { case 'decimal': case 'numeric': case 'float': case 'double': $row[ $col ] = (float)$value; break; case 'integer': case 'int': case 'bigint': case 'mediumint': case 'tinyint': case 'smallint': $row[ $col ] = (int)$value; break; } } $results[ $index ] = $row; }
Instrukcja switch może być łatwo modyfikowana i może zawierać funkcje daty itp. Na przykład w moim przypadku strona trzecia wypycha wartości walut do bazy danych jako ułamki dziesiętne, ale kiedy pobieram te dane i muszę je zwrócić jako JSON, potrzebuję, aby były to liczby, a nie ciągi.
Testowane z PHP 7, 7.2 i JQuery 2, 3.
źródło