четверг, 11 марта 2021 г.

Doctrine: ошибка парсинга запроса

На самом деле пост довольно специфический. Начну с описания проблемы, встреченной мной уже минимум два раза. Имеем обычный с виду код выполнения запроса:

$conn = $this->getEntityManager()->getConnection();
$conn->executeQuery($query, [
    'param1' => 42,
    'param2' => 'forty-two',
    'param3' => '%some_other_data%',
]);

При выполнении этого кода ловим ошибку типа такой:

SQLSTATE[08P01]: <<Unknown error>>: 7 ERROR:  bind message supplies 0 parameters, but prepared statement "pdo_stmt_000...." requires 3

Казалось бы, что может пойти не так? Мы взяли запрос с именованными параметрами, взяли данные для подстановки и передали всё это в Доктрину. Однако, практика показывает, что при неком специфичном тексте запроса Доктрина не справляется с парсингом текста запроса и считает, что в данном запросе нет именованных параметров. Исходя из моего опыта, такое случалось на запросах с огромным количеством :, так как именно двоеточие определяет начало именованного параметра.

В качестве запроса, ломающего Доктрину можно привести такой (использую postgresql, текст запроса очень приблизительный):

SELECT
    id,
    value::FLOAT,
    exec_date
FROM (
    VALUES
    (
        8095,
        41,
        '2020-01-02 10:48:17'
    ),
    --- Таких values тут сотни две
) as vs (id, value, exec_date)
JOIN
    some_table t ON vs.id = t.foreign_id::INT
WHERE
   t.created_at::TIMESTAMP + interval '3600 second' <= vs.executed_at::TIMESTAMP
   AND t.field_one = :param1
   AND t.field_two = :param2
   --- и еще что-нибудь

Найденное мной быстрое решение - это поменять именованные параметры (:param1) на позиционные (?), с такими данными Доктрина успешно справляется. Если есть желание - можете самостоятельно нырнуть в дебри и поковыряться в регулярках, а возможно где-то уже висит issue (но это не точно), или в третьей версии Доктрины это вообще уже исправлено.

среда, 17 февраля 2021 г.

Интеграция php-кода и html-верстки

Сегодня у нас урок для начинающих. Допустим, вы - начинающий программист, или верстальщик, или вообще пытались мимо проходить, но жизнь заставила соединить верстку (она же html-разметка) и php-код. Как это сделать с минимальными усилиями?

Итак, допустим у вас есть верстка для списка новостей:

<div>
  <h1>Это заголовок списка новостей</h1>
  <div class="some-class">
    <h2>Заголовок новости 1</h2>
    <p>Небольшой блок текста для ознакомления</p>
    <a href="/detail.php?id=1">Читать текст целиком</a>
    <span class="author">Автор новости: И. Иванов</span>
  </div>
  <div class="some-class">
    <h2>Заголовок новости 2</h2>
    <p>Небольшой блок текста для ознакомления</p>
    <a href="/detail.php?id=2">Читать текст целиком</a>
    <span class="author">Автор новости: И. Иванов</span>
  </div>
  <div class="some-class">
    <h2>Заголовок новости 3</h2>
    <p>Небольшой блок текста для ознакомления</p>
    <a href="/detail.php?id=3">Читать текст целиком</a>
    <span class="author">Автор новости: И. Иванов</span>
  </div>
</div>

И есть массив новостей $newsArray, полученный из БД/API/откуда-то ещё. Мы не будем рассматривать, как вы получили этот массив, будем считать, что он у вас есть.

Для лучшего понимания, что и как нужно сделать, разобьем нашу задачу на несколько шагов.