【发布时间】:2019-07-02 12:56:46
【问题描述】:
我有以下架构:
+---------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| someInt | int(11) | NO | | NULL | |
+---------+--------------+------+-----+---------+----------------+
当我运行以下脚本时,整数作为字符串返回。
$pdo = new \PDO("mysql:host={$db['host']};dbname={$db['dbname']};charset={$db['charset']}",$db['username'],$db['password'],array(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY=>true,\PDO::ATTR_ERRMODE=>\PDO::ERRMODE_EXCEPTION,\PDO::ATTR_DEFAULT_FETCH_MODE=>\PDO::FETCH_ASSOC));
var_dump($pdo->query('SELECT * FROM integerTesting')->fetchAll());
array(3) {
[0]=>
array(3) {
["id"]=>
string(1) "4"
["name"]=>
string(6) "Name 1"
["someInt"]=>
string(1) "1"
}
[1]=>
array(3) {
["id"]=>
string(1) "5"
["name"]=>
string(6) "Name 2"
["someInt"]=>
string(1) "2"
}
[2]=>
array(3) {
["id"]=>
string(1) "6"
["name"]=>
string(6) "Name 3"
["someInt"]=>
string(1) "3"
}
}
所以,我将PDO::ATTR_EMULATE_PREPARES 更改为FALSE,并得到我正在寻找的结果:
$pdo = new \PDO("mysql:host={$db['host']};dbname={$db['dbname']};charset={$db['charset']}",$db['username'],$db['password'],array(\PDO::ATTR_EMULATE_PREPARES=>false,\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY=>true,\PDO::ATTR_ERRMODE=>\PDO::ERRMODE_EXCEPTION,\PDO::ATTR_DEFAULT_FETCH_MODE=>\PDO::FETCH_ASSOC));
var_dump($pdo->query('SELECT * FROM integerTesting')->fetchAll());
array(3) {
[0]=>
array(3) {
["id"]=>
int(4)
["name"]=>
string(6) "Name 1"
["someInt"]=>
int(1)
}
[1]=>
array(3) {
["id"]=>
int(5)
["name"]=>
string(6) "Name 2"
["someInt"]=>
int(2)
}
[2]=>
array(3) {
["id"]=>
int(6)
["name"]=>
string(6) "Name 3"
["someInt"]=>
int(3)
}
}
我是否回答了自己的问题?不,因为我的问题明确指出,没有禁用ATTR_EMULATE_PREPARES。为什么这很重要?因为这样做显然会中断。我最初的问题如下,但我知道这不是一个真正的 Doctrine 问题,而是一个 PDO/MySQL 问题。
我有以下 Doctrine 实体:
<?php
use Doctrine\ORM\Mapping as ORM;
/**
* @Entity @Table(name="integerTesting")
**/
class IntegerTesting
{
/**
* @var int
*
* @Column(type="integer")
* @Id
* @GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/** @Column(type="string") */
protected $name;
/**
* @var int
*
* @Column( type="integer")
*/
protected $someInt;
public function getId()
{
return $this->id;
}
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
return $this;
}
public function getSomeInt()
{
return $this->someInt;
}
public function setSomeInt($someInt)
{
$this->someInt = $someInt;
return $this;
}
}
我添加一对或记录,然后读取一些记录,包括 Doctrine 的 findAll() 方法以及直接 PDO 查询:
<?php
require_once "bootstrap.php";
function addRow(int $i, $entityManager):void {
$e = new IntegerTesting();
$e->setName("Name $i");
$e->setSomeInt($i);
$entityManager->persist($e);
$entityManager->flush();
}
for ($i = 1; $i <= 3; $i++) {
addRow($i, $entityManager);
}
//Using Doctrine's findAll() method
var_dump($entityManager->getRepository('IntegerTesting')->findAll());
//Using direct PDO query
var_dump($entityManager->getConnection()->query('SELECT * FROM integerTesting')->fetchAll());
使用 Doctrine 的 findAll() 方法的输出返回整数列作为所需的整数类型。
array(3) {
[0]=>
object(IntegerTesting)#61 (3) {
["id":protected]=>
int(4)
["name":protected]=>
string(6) "Name 1"
["someInt":protected]=>
int(1)
}
[1]=>
object(IntegerTesting)#63 (3) {
["id":protected]=>
int(5)
["name":protected]=>
string(6) "Name 2"
["someInt":protected]=>
int(2)
}
[2]=>
object(IntegerTesting)#64 (3) {
["id":protected]=>
int(6)
["name":protected]=>
string(6) "Name 3"
["someInt":protected]=>
int(3)
}
}
但是,直接查询会将它们作为不需要的字符串返回:
array(3) {
[0]=>
array(3) {
["id"]=>
string(1) "4"
["name"]=>
string(6) "Name 1"
["someInt"]=>
string(1) "1"
}
[1]=>
array(3) {
["id"]=>
string(1) "5"
["name"]=>
string(6) "Name 2"
["someInt"]=>
string(1) "2"
}
[2]=>
array(3) {
["id"]=>
string(1) "6"
["name"]=>
string(6) "Name 3"
["someInt"]=>
string(1) "3"
}
}
我通过将PDO::ATTR_EMULATE_PREPARES 设置为FALSE 找到了解决方案,但是,经过艰苦的故障排除后,发现它破坏了 Doctrine 的某些其他方面(类类型继承,可能还有其他功能)。
如何防止 Doctrine 将整数作为字符串返回?
【问题讨论】:
-
在 Symfony 示例中,对象被数据水合,这就是它具有正确数据类型的原因。在第二个示例中,您将 PDO 与 MySQL 一起使用。默认情况下,它将返回字符串或 null。您可以将 MySQL 驱动程序更改为 mysqlnd,使用 symfony 的内置方法,或者从 PDO 查询中转换结果。
标签: php mysql pdo doctrine-orm doctrine