Запретить PHP, PDO и MySQL / MariaDB возвращать целые числа в виде строк без отключения ATTR_EMULATE_PREPARES - PullRequest
0 голосов
/ 02 июля 2019

У меня есть следующая схема:

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

Я добавляю паруили записывает, а затем читает некоторые записи как метод findAll () Doctrine, так и прямой запрос 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());

Вывод с использованием метода findAll () Doctrine возвращает целочисленные столбцы в качестве целочисленного типа.

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 возвращать целые числа в виде строк?

1 Ответ

0 голосов
/ 02 июля 2019

Ну, думаю, технически это не отвечает на вопрос, так как я отключаю \PDO::ATTR_EMULATE_PREPARES. Однако это работает для меня, так как я могу делать это для каждого запроса и, следовательно, не расстраивать доктрину.

    $pdo = $this->getEntityManager()->getConnection()->getWrappedConnection();
    $pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES,false);
...