PHP + PDO + MySQL: MySQL'den tamsayı ve sayısal sütunları PHP'de tam sayı ve sayısal olarak nasıl döndürürüm?


85

Stack Overflow'da bu sorunun birkaç kez tekrarlandığını gördüm, ancak hiçbiri sorunu yeterince araştırmıyor (veya en azından bana yardımcı olacak şekilde)

Buradaki sorun, bir DB sorgusunun PHP'de tamsayı sütunları için tamsayı veri türleri döndürmesidir. Bunun yerine sorgu, her sütunu bir dize türü olarak döndürür.

Yalnızca sonuçların dizeye dönüştürülmediğinden emin olmak için "PDO :: ATTR_STRINGIFY_FETCHES" öğesinin false olduğundan emin oldum .

Gördüğüm cevaplar:

  • Yapılamaz
    • Hayır, Mac OS X yüklü PHP / MySQL üzerinde çalışıyor
  • Kodunuza tüm değerlerinizi dökün yazın
    • Hayır, bunu yapmayacağım
  • Merak etmeyin, PHP gevşek yazılmıştır
    • Verilerim JSON olarak çıktı ve diğer birçok hizmet tarafından kullanılıyor, bazıları verilerin doğru biçimde olmasını gerektiriyor

Araştırmamdan bunun bir sürücü uygulama sorunu olduğunu anlıyorum.

Birçok kaynak, MySQL yerel sürücüsünün sayısal türlerin döndürülmesini desteklemediğini iddia ediyor. Bu, Mac OS X üzerinde çalıştığı için doğru görünmüyor. " Linux'taki MySQL yerel sürücüsü özelliği desteklemiyor" demek istemedikçe.

Bu, Mac OS X'e yüklediğim sürücü / ortam hakkında özel bir şey olduğu anlamına geliyor. Bir düzeltme uygulamak için farklılıkları belirlemeye çalışıyorum, ancak bunları nasıl kontrol edeceğime dair bilgilerimle sınırlıyım.

Farklılıklar:

  • OS X üzerinde PHP, Home Brew aracılığıyla derlenmiş ve kurulmuştur
  • Ubuntu'da PHP, "apt-get install php5-dev" aracılığıyla kuruldu
  • OS X üzerinde PHP, OS X üzerinde de çalışan bir MySQL sunucusuna bağlanıyor
    • Sunucu sürümü: 5.1.71-log Kaynak dağıtımı
  • Ubuntu'daki PHP, bir Rackspace Bulut Veritabanına bağlanıyor
    • Sunucu sürümü: 5.1.66-0 + squeeze1 (Debian)

Ubuntu ortamı

  • Sürüm: 10.04.1
  • PHP 5.4.21-1 + debphp.org ~ lucid + 1 (cli) (inşa: 21 Ekim 2013 08:14:37)
  • php -i

    pdo_mysql

    MySQL için PDO Sürücüsü => etkin İstemci API sürümü => 5.1.72

Mac OS X ortamı

  • 10.7.5
  • PHP 5.4.16 (cli) (inşa: 22 Ağu 2013 09:05:58)
  • php -i

    pdo_mysql

    MySQL için PDO Sürücüsü => etkin İstemci API sürümü => mysqlnd 5.0.10 - 20111026 - $ Id: e707c415db32080b3752b232487a435ee0372157 $

PDO bayrakları kullanıldı

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,

Herhangi bir yardım ve uzmanlık takdir edilecektir :) Cevabı bulursam kesinlikle buraya tekrar yazacağım.


2
Bu MySQL'in sorumluluğundadır. İnanıyorum
Sağduyu

Tam olarak aynı sorum var, ancak MS SQL Server için. Bunun için mysqlnd'ye benzer güçlü bir şekilde yazılmış bir kitaplık var mı? Bulabildiğim en son sürücüler tüm dizeleri döndürüyor.
GSerg

Yanıtlar:


122

Çözüm, php için mysqlnd sürücüsünü kullandığınızdan emin olmaktır .

Mysqlnd kullanmadığınızı nasıl anlarsınız?

Görüntülerken php -i, orada olacağım hayır "mysqlnd" nin söz. pdo_mysqlBölüm aşağıdaki gibi bir şey olacak:

pdo_mysql

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

Nasıl kurarsınız?

L için en montaj kılavuzları / A / A / P göstermektedir apt-get install php5-mysql, ancak MySQL yerel sürücü farklı bir paket ile yüklenir: php5-mysqlnd. Bunun ppa: ondrej / php5-oldstable ile mevcut olduğunu buldum .

Yeni sürücüye geçmek için (Ubuntu'da):

  • Eski sürücüyü kaldırın:
    apt-get remove php5-mysql
  • Yeni sürücüyü kurun:
    apt-get install php5-mysqlnd
  • Apache2'yi yeniden başlatın:
    service apache2 restart

Sürücünün kullanıldığını nasıl kontrol ederim?

Şimdi bölümde php -iaçıkça "mysqlnd" den bahsedecek pdo_mysql:

pdo_mysql

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

PDO ayarları

Emin olun PDO::ATTR_EMULATE_PREPARESolduğunu false(Varsayılanlarınızı kontrol etmek veya ayarlamak):
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Emin olun PDO::ATTR_STRINGIFY_FETCHESolduğunu false(Varsayılanlarınızı kontrol etmek veya ayarlamak):
$pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);

Döndürülen değerler

  • Kayan nokta türleri (FLOAT, DOUBLE), PHP floats olarak döndürülür.
  • Tam sayı türleri (INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT †) PHP tamsayıları olarak döndürülür.
  • Sabit Nokta türleri (DECIMAL, NUMERIC) dizeler olarak döndürülür.

† 64 bit işaretli int (9223372036854775807) değerinden daha büyük bir değere sahip BIGINT'ler bir dize (veya 32 bit sistemde 32 bit) olarak dönecektir

    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
Mysqlnd'nin bu sürümü etkinleştirilse bile, DECIMALS'in yine de dizeler olarak gönderileceğini unutmayın ... (FLOATS yüzer olarak döndürülecek olsa da!): / Kaynak: Test ettim.
Pere

4
Ayrıca PDO :: ATTR_STRINGIFY_FETCHES'in bununla hiçbir ilgisi olmadığını unutmayın - denedim ve sonuç üzerinde hiçbir etkisi yok ve bu gönderide kullanıcı @Josh Davis bunun MySQL ile ilgisi olmadığını söylüyor.
Pere

1
Teşekkürler, DECIMAL türü hakkında daha fazla araştırma yaptım ve notları güncelledim.
stephenfrank

4
@pere bu doğru davranıştır. DECIMAL, sayısal bir tür değildir. Sayılar için bir dize biçimidir. Böylece: yerine 0.30olarak dönebilirsiniz . Bunun için ondalık kullanılır ... bu yüzden bu doğru davranış"0.30"0.3
Max Cuttins

neden bu lanet bir uzlaşmadır? PDO::ATTR_EMULATE_PREPARESAdlandırılmış bir parametreyi bir kereden fazla kullanmam gerekiyor
Gaby_64

5

Kabul edilen bu cevap işe yarıyor ve bu soru için Google'da en popüler cevap gibi görünüyor. Benim sorunum, bir uygulamayı birden çok ortama dağıtmam ve her zaman doğru sürücüyü yükleyemem, ayrıca ondalık sayıların dize değil sayısal olmasına ihtiyacım var. Bu yüzden, JSON kodlamasından önce duruma uyması için kolayca değiştirilebilen bir vaka yazmak için bir rutin oluşturdum. Yörüngeden fırlatmak gibi bir şey.

İlk olarak, tablodan sütunları almak için "sütunları göster" seçeneğini kullanın. mysql sorgusu "'colmunname' gibi tablodan SÜTUNLARI GÖSTER": sorular

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

Ardından, yinelemeyi kolaylaştırmak için türleri sütun adına göre dizinlenmiş bir diziye alın. Gösteri sütunlarından ayarlanan sonuçların $ column_from_table adlı bir değişkende olduğunu varsayar. http://php.net/manual/en/function.array-column.php

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

Daha sonra, varchar (32) veya ondalık (14,6) gibi bir şey olacak olan türden parantezleri kaldırmak istiyoruz.

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

Şimdi, dizin olarak sütun adı ve değer olarak biçimlendirilmiş tür ile ilişkili bir dizimiz var, örneğin:

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

Şimdi, tablonuzdan seçiminizi yaptığınızda, sonuçları yineleyebilir ve değeri uygun türe çevirebilirsiniz:

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

Switch ifadesi kolayca uygun olacak şekilde değiştirilebilir ve tarih işlevleri vb. İçerebilir. Örneğin, benim durumumda bir üçüncü taraf para birimi değerlerini ondalık sayı olarak veritabanına itiyor, ancak bu verileri aldığımda ve şu şekilde döndürmem gerektiğinde JSON, bunların dizi değil sayı olmasına ihtiyacım var.

PHP 7, 7.2 ve JQuery 2, 3 ile test edilmiştir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.