2016-01-21 79 views
1

为了显示我的问题,我提出了两个函数。第一个向Laravel询问PDO实例并查询数据库。在第二个我自己instanciate一个新的。 来自Laravel的第一个结果不准确。第二个给出正确的结果。Laravel 5.0 PDO从MySQL查询float会给出不准确的结果

表defenition会是这样的:

CREATE TABLE IF NOT EXISTS `event` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `level` float DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 

这是第一个功能:

public function testpdo1() { 
    $pdo = DB::connection('myconnection')->getPdo();   
    $query = "SELECT level FROM event LIMIT 4"; 
    $result = $pdo->query($query); 
    foreach ($result as $row) { 
     print $row[0] ."\n"; 
    } 
} 

其中给出以下结果:

102.09999847412 
97.900001525879 
95.300003051758 
94.099998474121 

这是第二个功能:

public function testpdo2() { 
    $pdo = new PDO('dsn', 'user', 'pass'); 
    $query = "SELECT level FROM event LIMIT 4"; 
    $result = $pdo->query($query); 
    foreach ($result as $row) { 
     print $row[0] ."\n"; 
    } 
} 

其中给出以下结果:

102.1 
97.9 
95.3 
94.1 

在最后的是正确的结果。

有没有办法让Laravel的行为像第二个功能?

我想差别在于PDO设置。我尝试设置PDO :: ATTR_STRINGIFY_FETCHES,但无济于事。我也在第二个函数中试过,看看我能否让第二个错误。但它没有奏效。

也许我做了一些错误的设置这样的属性。随着laravel(功能1)我试图/config/database.php将其设置为我的连接选项:

'connections' => [ 

    'myconnection' => [ 
     'driver' => 'mysql', 
     'host'  => env('DB_HOST', 'localhost'), 
     'database' => env('DB_DATABASE', 'forge'), 
     'username' => env('DB_USERNAME', 'forge'), 
     'password' => env('DB_PASSWORD', ''), 
     'charset' => 'utf8', 
     'collation' => 'utf8_unicode_ci', 
     'prefix' => '', 
     'strict' => false, 
     'options' => array (
      PDO::ATTR_STRINGIFY_FETCHES => true, 
     ), 
    ], 
.... 

与我

$pdo = new PDO('dsn', 'user', 'pass', [PDO::ATTR_STRINGIFY_FETCHES => true]); 

,并试图将其与

第二功能
$pdo->setAttribute (PDO::ATTR_STRINGIFY_FETCHES , true); 

实例化后,有一个错误的值。它似乎没有任何区别...

这个问题接近我的问题:PHP PDO query returns inaccurate value for FLOAT fields 。但是由于我的第二个功能给出了正确的答案,似乎有可能得到准确的答案。

@Ragu Swaminathan建议第二个函数给出四舍五入的值。只是要清楚:那些是数据库中的值。

mysql> select level from event LIMIT 4; 
+-------+ 
| level | 
+-------+ 
| 102.1 | 
| 97.9 | 
| 95.3 | 
| 94.1 | 
+-------+ 
4 rows in set (0.00 sec) 

当我在功能1查询中使用四舍五入的值将成为与从功能2.这是围绕一个可能的工作价值观,但我希望有一个更好的解决方案。

+0

实际上第二个函数给你四舍五入的结果,而第一个给你的原始值..但两者似乎是相同的.. –

回答

0

这两个函数行为不同的原因确实在PDO设置中。 参数PDO :: ATTR_EMULATE_PREPARES的默认值为true。 Laravel将此参数设置为false。

所以@拉古斯瓦米纳森是对的。第二个函数给了我四舍五入的值。与mysql_client,phpmyadmin,perl等一样

我用我想分享的第二个函数做了一些测试。我改变了一下。

public function testpdo2() { 
    $pdo = new PDO('dsn', 'user', 'pass'); 
    $query = "SELECT level FROM `test`"; 
    $result = $pdo->query($query); 
    foreach ($result as $row) { 
     print gettype($row[0]).' : '.$row[0]."<br>"; 
    } 
} 

结果是

string : 102.1 
string : 97.9 
string : 95.3 
string : 94.1 

所以我得到的字符串

当我把这一行instanciating PDO

$pdo->setAttribute (PDO::ATTR_EMULATE_PREPARES, false); 

结果是

double : 102.09999847412 
double : 97.900001525879 
double : 95.300003051758 
double : 94.099998474121 

当我还(!),加入这一行

$pdo->setAttribute (PDO::ATTR_STRINGIFY_FETCHES , true); 

结果是

string : 102.09999847412 
string : 97.900001525879 
string : 95.300003051758 
string : 94.099998474121 

所以这就是为什么这似乎并没有帮助

我最后的测试是一个将值102.09999847412插入表中。 而“正常”答案回来为102.1

结论是:浮动不被信任。 但我们知道已经;-)