Справка - часто задаваемые вопросы о PDO - программирование
Подтвердить что ты не робот

Справка - часто задаваемые вопросы о PDO

Что это?

Это список часто задаваемых вопросов, касающихся объектов данных PHP

Почему это?

Поскольку у PDO есть некоторые функции, неизвестные обычным пользователям PHP, вопросы относительно подготовленных операторов и обработки ошибок в PDO довольно часты. Таким образом, это просто место, где все они могут быть найдены.

Что мне делать здесь?

Если ваш вопрос был закрыт с этим списком, пожалуйста, найдите свой вопрос ниже и примените исправление к вашему коду. Также неплохо взять краткий взгляд на другие вопросы, чтобы подготовиться к другим распространенным ловушкам.

Список

См. также

4b9b3361

Ответ 1

Ошибка PDO-запроса, но я не вижу никаких ошибок. Как получить сообщение об ошибке из PDO?

Чтобы иметь возможность видеть ошибки базы данных, нужно установить PDO errmode на исключения. Исключения лучше обычных ошибок по-разному: они всегда содержат трассировку стека, их можно поймать с помощью try..catch или обработать с помощью специального обработчика ошибок. И даже необработанные, они действуют как обычные ошибки PHP, предоставляя всю важную информацию, следуя настройкам отчетов об ошибках на сайте.

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

$dsn = "mysql:host=$host;dbname=$db;charset=utf8";
$opt = array(
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    // other options 
);
$pdo = new PDO($dsn, $user, $pass, $opt);

Таким образом, вы всегда будете уведомлены обо всех ошибках базы данных, возникающих во время выполнения запроса. Обратите внимание, что вы должны уметь видеть ошибки PHP вообще. На реальном сайте вам нужно заглянуть в журналы ошибок, поэтому настройки должны быть

error_reporting(E_ALL);
ini_set('display_errors',0);
ini_set('log_errors',1);

в то время как на локальном сервере разработки это нормально делать ошибки на экране:

error_reporting(E_ALL);
ini_set('display_errors',1);

и, конечно же, вы никогда не должны использовать оператор подавления ошибок (@) перед вашими заявлениями PDO.

Кроме того, из-за многих плохих примеров, рассказывающих об обертке каждого оператора PDO в блок try..catch, я должен сделать отдельное примечание:

НЕ используйте оператор try..catch для эхо-сообщения об ошибке. Исключение для исключений уже отлично подходит для этой цели, поскольку оно будет действовать точно так же, как и другие ошибки PHP - так что вы может определять поведение, используя параметры сайта - так что у вас будет сообщение об ошибке без этого бесполезного кода. В то время как безоговорочное эхо-сообщение об ошибке может выявить некоторую конфиденциальную информацию потенциальному злоумышленнику, но путайте честного посетителя,

  • настраиваемый обработчик исключений может быть добавлен позже, но не требуется. Специально для новых пользователей рекомендуется использовать необработанные исключения, поскольку они чрезвычайно информативны, полезны и безопасны.
  • Используйте try..catch только в том случае, если вы собираетесь обрабатывать сама ошибка - скажем, откат транзакции.

Ответ 2

Отчет, подготовленный PDO, вызывает ошибку в предложении LIMIT

В целях совместимости PDO просто подражает подготовленным операторам, заменяя заполнители фактическими данными, вместо отправки их на сервер отдельно, если не указано иное. И с "ленивой" привязкой (используя массив в execute()), PDO будет обрабатывать каждый параметр как строку. В результате подготовленный LIMIT ?,? запрос становится LIMIT '10', '10', что является недопустимым синтаксисом, который вызывает запрос с ошибкой.

Эта проблема может быть решена либо

  • отключив режим эмуляции (поскольку MySQL может сортировать все заполнители правильно):

    $conn->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
    
  • путем привязки и установки правильного типа (PDO:: PARAM_INT) явно:

    $stm = $pdo->prepare('SELECT * FROM table LIMIT ?, ?');
    $stm->bindValue(1, $limit_from,PDO::PARAM_INT);
    $stm->bindValue(2, $per_page,PDO::PARAM_INT);
    $stm->execute();
    $data = $stm->fetchAll();
    

Ответ 3

Как я могу использовать подготовленные операторы с помощью оператора LIKE?

Подготовленный оператор может представлять полный литерал данных. Не является частью литерального, не сложного выражения или идентификатора. Но только строка или число только. Итак, очень распространенная ошибка - это такой запрос:

$sql = "SELECT * FROM t WHERE column LIKE '%?%'";

Если вы немного поразмышляете над этим вопросом, вы поймете, что, находясь внутри одинарных кавычек, знак вопроса становится буквальным вопросительным знаком, без какого-либо особого значения для подготовленных операторов.

Итак, нужно отправить полный строковый литерал с помощью подготовленного оператора. Возможны два способа:

  • сначала сначала создайте FULL выражение:

    $name = "%$name%";
    $stm  = $pdo->prepare("SELECT * FROM table WHERE name LIKE ?");
    $stm->execute(array($name));
    $data = $stm->fetchAll();
    
  • или используйте конкатенацию внутри запроса

    $sql = "SELECT * FROM t WHERE column LIKE concat('%',?,'%')";
    

хотя последнее кажется слишком раздутым.