PHP + PDO + MySQL: Làm cách nào để trả về các cột số nguyên và số từ MySQL dưới dạng số nguyên và số trong PHP?


85

Tôi đã thấy câu hỏi này lặp lại một vài lần trên Stack Overflow nhưng không có cách nào khám phá đầy đủ vấn đề (hoặc ít nhất là theo cách hữu ích đối với tôi)

Vấn đề là một truy vấn DB sẽ trả về kiểu dữ liệu số nguyên trong PHP cho các cột số nguyên. Thay vào đó, truy vấn trả về mọi cột dưới dạng một loại chuỗi.

Tôi đã đảm bảo rằng "PDO :: ATTR_STRINGIFY_FETCHES" nếu sai chỉ để đảm bảo kết quả không được chuyển thành chuỗi.

Các câu trả lời mà tôi đã xem:

  • Nó không thể được thực hiện
    • Không, nó hoạt động trên Mac OS X được cài đặt PHP / MySQL
  • Nhập truyền tất cả các giá trị của bạn trong mã của bạn
    • Không, tôi sẽ không làm điều đó
  • Đừng lo lắng về điều đó, PHP được gõ lỏng lẻo
    • Dữ liệu của tôi được xuất ra dưới dạng JSON và được sử dụng bởi nhiều dịch vụ khác, một số yêu cầu dữ liệu ở định dạng chính xác

Từ nghiên cứu của mình, tôi hiểu rằng đây là vấn đề triển khai trình điều khiển.

Nhiều nguồn cho rằng trình điều khiển gốc MySQL không hỗ trợ trả về kiểu số. Điều này có vẻ không đúng vì nó hoạt động trên Mac OS X. Trừ khi họ muốn nói rằng "trình điều khiển gốc MySQL trên Linux không hỗ trợ tính năng này".

Điều này ngụ ý rằng có điều gì đó đặc biệt về trình điều khiển / môi trường mà tôi đã cài đặt trên Mac OS X. Tôi đã cố gắng xác định sự khác biệt để áp dụng bản sửa lỗi nhưng tôi bị hạn chế bởi kiến ​​thức về cách kiểm tra những điều này.

Sự khác biệt:

  • PHP trên OS X được biên dịch và cài đặt thông qua Home Brew
  • PHP trên Ubuntu đã được cài đặt thông qua "apt-get install php5-dev"
  • PHP trên OS X đang kết nối với máy chủ MySQL cũng chạy trên OS X
    • Phiên bản máy chủ: 5.1.71-log Phân phối nguồn
  • PHP trên Ubuntu đang kết nối với Cơ sở dữ liệu đám mây Rackspace
    • Phiên bản máy chủ: 5.1.66-0 +quee1 (Debian)

Môi trường Ubuntu

  • Phiên bản: 10.04.1
  • PHP 5.4.21-1 + debphp.org ~ lucid + 1 (cli) (xây dựng: 21/10/2013 08:14:37)
  • php -i

    pdo_mysql

    Trình điều khiển PDO cho MySQL => phiên bản API ứng dụng khách được kích hoạt => 5.1.72

Môi trường Mac OS X

  • 10,7,5
  • PHP 5.4.16 (cli) (xây dựng: 22/08/2013 09:05:58)
  • php -i

    pdo_mysql

    Trình điều khiển PDO cho MySQL => phiên bản API ứng dụng được kích hoạt => mysqlnd 5.0.10 - 20111026 - $ Id: e707c415db32080b3752b232487a435ee0372157 $

Cờ PDO được sử dụng

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,

Mọi sự giúp đỡ và chuyên môn sẽ được đánh giá cao :) Tôi chắc chắn sẽ đăng lại ở đây nếu tôi tìm thấy câu trả lời.


2
Đó là trách nhiệm của mysqlnd. Tôi tin rằng
bạn Common Sense

Tôi có cùng một câu hỏi, nhưng đối với MS SQL Server. Có một thư viện được đánh máy mạnh mẽ cho điều đó, giống như mysqlnd? Các trình điều khiển mới nhất tôi có thể tìm thấy trả về tất cả các chuỗi.
GSerg

Câu trả lời:


121

Giải pháp là đảm bảo rằng bạn đang sử dụng trình điều khiển mysqlnd cho php.

Làm thế nào để bạn biết rằng bạn không sử dụng mysqlnd?

Khi xem php -isẽ không đề cập đến "mysqlnd". Các pdo_mysqlphần sẽ có một cái gì đó như thế này:

pdo_mysql

PDO Driver for MySQL => enabled Client API version => 5.1.72

Bạn cài đặt nó như thế nào?

Hầu hết các hướng dẫn cài đặt cho L / A / M / P đề nghị apt-get install php5-mysqlnhưng người lái xe bản địa cho MySQL được cài đặt bởi một gói khác nhau: php5-mysqlnd. Tôi thấy rằng điều này có sẵn với ppa: ondrej / php5-oldstable .

Để chuyển sang trình điều khiển mới (trên Ubuntu):

  • Xóa trình điều khiển cũ:
    apt-get remove php5-mysql
  • Cài đặt trình điều khiển mới:
    apt-get install php5-mysqlnd
  • Khởi động lại apache2:
    service apache2 restart

Làm cách nào để kiểm tra xem trình điều khiển đang được sử dụng?

Bây giờ php -isẽ đề cập đến "mysqlnd" một cách rõ ràng trong pdo_mysqlphần:

pdo_mysql

PDO Driver for MySQL => enabled
Client API version => mysqlnd 5.0.10 - 20111026 - $Id:      e707c415db32080b3752b232487a435ee0372157 $

Cài đặt PDO

Đảm bảo rằng PDO::ATTR_EMULATE_PREPARESfalse(kiểm tra giá trị mặc định của bạn hoặc thiết lập nó):
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Đảm bảo rằng PDO::ATTR_STRINGIFY_FETCHESfalse(kiểm tra giá trị mặc định của bạn hoặc thiết lập nó):
$pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);

Giá trị trả về

  • Các kiểu dấu phẩy động (FLOAT, DOUBLE) được trả về dưới dạng các dấu phẩy động PHP.
  • Các kiểu số nguyên (INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT †) được trả về dưới dạng số nguyên PHP.
  • Các loại điểm cố định (DECIMAL, NUMERIC) được trả về dưới dạng chuỗi.

† BIGINTs có giá trị lớn hơn 64 bit có dấu int (9223372036854775807) sẽ trả về dưới dạng chuỗi (hoặc 32 bit trên hệ thống 32 bit)

    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)

3
Lưu ý rằng ngay cả khi bật phiên bản mysqlnd này, DECIMALS sẽ vẫn được gửi dưới dạng chuỗi ... (mặc dù FLOATS sẽ được trả về dưới dạng phao!): / Nguồn: Tôi đã thử nghiệm nó.
Pere

4
Cũng lưu ý rằng PDO :: ATTR_STRINGIFY_FETCHES không liên quan gì đến nó - tôi đã thử và nó không ảnh hưởng đến kết quả và trong bài đăng này, người dùng @Josh Davis nói rằng nó không liên quan đến MySQL.
Pere

1
Cảm ơn, tôi đã điều tra thêm và cập nhật các ghi chú về loại DECIMAL.
stephenfrank

4
@pere đây là hành vi đúng. DECIMAL không phải là một kiểu số. Đó là một định dạng chuỗi cho các số. Vì vậy, bạn có thể trở lại: 0.30như "0.30"thay vì 0.3. Số thập phân được sử dụng cho điều này ... vì vậy đây là hành vi đúng
Max Cuttins

tại sao nó là một thỏa hiệp chết tiệt? Tôi cần PDO::ATTR_EMULATE_PREPARESsử dụng một tham số được đặt tên nhiều hơn một lần
Gaby_64 16/12/19

4

Câu trả lời được chấp nhận này hoạt động và có vẻ là câu trả lời phổ biến nhất trên Google cho câu hỏi này. Vấn đề của tôi là tôi cần triển khai một ứng dụng cho nhiều môi trường và không phải lúc nào tôi cũng có khả năng cài đặt đúng trình điều khiển, ngoài ra tôi cần số thập phân là số chứ không phải chuỗi. Vì vậy, tôi đã tạo một thói quen để gõ chữ hoa chữ thường trước khi mã hóa JSON, dễ dàng sửa đổi cho phù hợp. Nó giống như đưa nó khỏi quỹ đạo.

Đầu tiên, sử dụng "hiển thị các cột từ" để lấy các cột từ bảng. truy vấn mysql "HIỂN THỊ CÁC CỘT TỪ bảng như 'colmunname'": câu hỏi

$query = 'SHOW COLUMNS FROM ' . $table; //run with mysqli or PDO 

Sau đó, lấy các kiểu vào một mảng được lập chỉ mục theo tên cột để dễ dàng lặp lại. Giả sử kết quả được đặt từ các cột hiển thị nằm trong một biến có tên $ column_from_table. http://php.net/manual/en/ Chức năng.array-column.php

$column_types = array_column( $columns_from_table, 'Type', 'Field');

Tiếp theo, chúng tôi muốn xóa dấu ngoặc đơn khỏi kiểu, sẽ là một cái gì đó như varchar (32) hoặc decimal (14,6)

foreach( $column_types as $col=>$type )
{
    $len = strpos( $type, '(' );
    if( $len !== false )
    {
        $column_types[ $col ] = substr( $type, 0, $len );
    }
}

Bây giờ chúng ta có một mảng được liên kết với tên cột là chỉ mục và kiểu được định dạng là giá trị, ví dụ:

Array
(
    [id] => int
    [name] => varchar
    [balance] => decimal
    ...
)

Bây giờ, khi bạn thực hiện lựa chọn từ bảng của mình, bạn có thể lặp lại các kết quả và truyền giá trị sang kiểu thích hợp:

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;
}

Câu lệnh switch có thể dễ dàng sửa đổi cho phù hợp và có thể bao gồm các hàm ngày, v.v. Ví dụ: trong trường hợp của tôi, bên thứ ba đang đẩy các giá trị tiền tệ vào cơ sở dữ liệu dưới dạng số thập phân, nhưng khi tôi lấy dữ liệu đó và cần trả lại nó như JSON, tôi cần chúng là số, không phải chuỗi.

Đã thử nghiệm với PHP 7, 7.2 và JQuery 2, 3.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.