模拟 PDO 获取失败情况 [英] Simulate a PDO fetch failure situation

查看:24
本文介绍了模拟 PDO 获取失败情况的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

符合php文档,PDO方法fetch() 在没有找到记录时返回值 FALSE 在失败时(例如,当数据库出现问题时)访问).

Conform to the php docs, the PDO method fetch() returns the value FALSE both when no records are found AND on failure (e.g. when something goes wrong regarding the database access).

假设,我将 PHP 错误报告系统设置为在失败时抛出异常:

Let's suppose, I set the PHP error reporting system to throw exceptions on failure:

PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION

我需要一个案例,fetch() 方法会抛出异常的情况.为什么?因为我想检查,所以要 100% 确定 fetch() 在失败时抛出异常,而不仅仅是在失败时返回 FALSE.

I need a case, a situation in which the fetch() method will throw an exception. Why? Because I want to check, to be 100% sure that fetch() throws an exception on failure, and doesn't just return FALSE on failure.

如果是这样的话,那么我确实会认为 fetch() 返回的 FALSE 是在 db 表中找不到任何记录的结果.

If that would be the case, then I would indeed consider the FALSE returned by fetch() as the result of not finding any records in the db table.

那么,我的问题是:你知道一种方法来模拟 fetch() 方法的失败情况吗?

So, my question would be: Do you know a way to simulate a failure situation for the fetch() method?

谢谢.

PS:我的问题的答案将帮助我找到其他问题的答案:PHP PDO fetch 在没有找到记录且失败时返回 FALSE

P.S.: The answer to my question will help me find the answer for my other question: PHP PDO fetch returns FALSE when no records found AND on failure

编辑 1:

我还准备了一个示例,展示我如何处理异常.这是一个简单的 sql 查询,从 users 表中获取用户:

I also prepared an example, to show how I handle the exceptions. It's about a simple sql query, fetching a user from a users table:

<?php

// Activate error reporting.
error_reporting(E_ALL);
ini_set('display_errors', 1);

try {

    // Create a PDO instance as db connection to a MySQL db.
    $connection = new PDO(
            'mysql:host=localhost;port=3306;dbname=mydb;charset=utf8'
            , 'myuser'
            , 'mypass'
            , array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_EMULATE_PREPARES => FALSE,
        PDO::ATTR_PERSISTENT => TRUE
            )
    );

    // Define the sql statement.
    $sql = 'SELECT * FROM users WHERE name = :name';

    /*
     * Prepare and validate the sql statement.
     * 
     * --------------------------------------------------------------------------------
     * If the database server cannot successfully prepare the statement, PDO::prepare() 
     * returns FALSE or emits PDOException (depending on error handling settings).
     * --------------------------------------------------------------------------------
     */
    $statement = $connection->prepare($sql);

    if (!$statement) {
        throw new UnexpectedValueException('The sql statement could not be prepared!');
    }

    // Bind the input parameter to the prepared statement.
    $bound = $statement->bindValue(':name', 'Sarah', PDO::PARAM_STR);

    // Validate the binding of the input parameter.
    if (!$bound) {
        throw new UnexpectedValueException('An input parameter can not be bound!');
    }

    /*
     * Execute the prepared statement.
     * 
     * ------------------------------------------------------------------
     * PDOStatement::execute returns TRUE on success or FALSE on failure.
     * ------------------------------------------------------------------
     */
    $executed = $statement->execute();

    if (!$executed) {
        throw new UnexpectedValueException('The prepared statement can not be executed!');
    }

    /*
     * Fetch and validate the result set.
     * 
     * =========================================================
     * Note:
     * =========================================================
     * PDOStatement::fetch returns FALSE not only on failure,
     * but ALSO when no record is found!
     * 
     * Instead, PDOStatement::fetchAll returns FALSE on failure,
     * but an empty array if no record is found. This is the
     * natural, desired behaviour.
     * =========================================================
     */
    $resultset = $statement->fetch(PDO::FETCH_ASSOC);

    if ($resultset === FALSE) {
        throw new UnexpectedValueException('Fetching data failed!');
    }

    // Display the result set.
    var_dump($resultset);
    echo '<pre>' . print_r($resultset, TRUE) . '</pre>';

    // Close connection.
    $connection = NULL;
} catch (PDOException $exc) {
    echo '<pre>' . print_r($exc, TRUE) . '</pre>';
    exit();
} catch (Exception $exc) {
    echo '<pre>' . print_r($exc, TRUE) . '</pre>';
    exit();
}

我使用了以下创建表语法:

I used the following create table syntax:

DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=124 DEFAULT CHARSET=utf8;

以及下表中的值:

INSERT INTO `users` (`id`, `name`)
VALUES
    (1,'Sarah'),
    (2,'John');

所以,表格如下所示:

id  name
--------
1   Sarah
2   John

推荐答案

最后,我找到了一个案例,让我可以测试一下,如果 PDOStatement::fetch 确实会在失败时抛出异常.

Finally, I found a case, which allowed me to test, if PDOStatement::fetch would indeed throw an exception on failure.

文章 利用 PDO 的获取模式 介绍了这样的一种情况.它基于使用 PDOStatement::fetchAllPDO::FETCH_KEY_PAIR 常量作为参数传递.

The article Taking advantage of PDO’s fetch modes presents such a situation. It is based on the use of PDOStatement::fetchAll with PDO::FETCH_KEY_PAIR constant passed as argument.

所以,我自己进行了测试.但我改用了 PDOStatement::fetch 方法.根据定义,PDO::FETCH_KEY_PAIR 常量要求数据源表只包含两列.在我的测试中,我定义了三个表格列.PDOStatement::fetch 已将此情况识别为失败并抛出异常:

So, I ran a test myself. But I used the PDOStatement::fetch method instead. Per definition, the PDO::FETCH_KEY_PAIR constant requires that the data source table contains only two columns. In my test I defined three table columns. PDOStatement::fetch has recognized this situation as a failure and had thrown an exception:

SQLSTATE[HY000]:一般错误:PDO::FETCH_KEY_PAIR 获取模式要求结果集正好包含 2 列.

SQLSTATE[HY000]: General error: PDO::FETCH_KEY_PAIR fetch mode requires the result set to contain extactly 2 columns.

结论:

  • PDOStatement::fetch 如果没有找到记录,则返回 FALSE.
  • PDOStatement::fetch 在失败的情况下抛出 - 实际上 - 一个异常.
  • Conclusion:

    • PDOStatement::fetch returns FALSE, if no records are found.
    • PDOStatement::fetch throws - indeed - an exception in case of failure.
      • 如果没有找到记录,PDOStatement::fetchAll 会返回一个空数组.
      • PDO::FETCH_KEY_PAIR 常量未记录在 PDOStatement::fetch 官方页面.
      • Instead, PDOStatement::fetchAll returns an empty array, if no records are found.
      • The PDO::FETCH_KEY_PAIR constant is not documented on the PDOStatement::fetch official page.

      我要感谢所有试图帮助我找到问题答案的用户.你有我的感激之情!

      I want to thank to all the users who tried to help me finding the answer to my question. You have my appreciation!

      <?php
      
      // Activate error reporting.
      error_reporting(E_ALL);
      ini_set('display_errors', 1);
      
      try {
      
          // Create a PDO instance as db connection to a MySQL db.
          $connection = new PDO(
                  'mysql:host=localhost;port=3306;dbname=tests;charset=utf8'
                  , 'root'
                  , 'root'
                  , array(
              PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
              PDO::ATTR_EMULATE_PREPARES => FALSE,
              PDO::ATTR_PERSISTENT => TRUE
                  )
          );
      
          // Define the sql statement.
          $sql = 'SELECT * FROM users WHERE name = :name';
      
          /*
           * Prepare the sql statement.
           * 
           * --------------------------------------------------------------------------------
           * If the database server cannot successfully prepare the statement, PDO::prepare() 
           * returns FALSE or emits PDOException (depending on error handling settings).
           * --------------------------------------------------------------------------------
           */
          $statement = $connection->prepare($sql);
      
          // Validate the preparation of the sql statement.
          if (!$statement) {
              throw new UnexpectedValueException('The sql statement could not be prepared!');
          }
      
          // Bind the input parameter to the prepared statement.
          $bound = $statement->bindValue(':name', 'Sarah', PDO::PARAM_STR);
      
          // Validate the binding of the input parameter.
          if (!$bound) {
              throw new UnexpectedValueException('An input parameter can not be bound!');
          }
      
          /*
           * Execute the prepared statement.
           * 
           * ------------------------------------------------------------------
           * PDOStatement::execute returns TRUE on success or FALSE on failure.
           * ------------------------------------------------------------------
           */
          $executed = $statement->execute();
      
          // Validate the execution of the prepared statement.
          if (!$executed) {
              throw new UnexpectedValueException('The prepared statement can not be executed!');
          }
      
          // Fetch the result set.
          $resultset = $statement->fetch(PDO::FETCH_KEY_PAIR);
      
          // If no records found, define the result set as an empty array.
          if ($resultset === FALSE) {
              $resultset = [];
          }
      
          // Display the result set.
          var_dump($resultset);
      
          // Close connection.
          $connection = NULL;
      } catch (PDOException $exc) {
          echo '<pre>' . print_r($exc->getMessage(), TRUE) . '</pre>';
          exit();
      } catch (Exception $exc) {
          echo '<pre>' . print_r($exc->getMessage(), TRUE) . '</pre>';
          exit();
      }
      

      创建表语法:

      DROP TABLE IF EXISTS `users`;
      CREATE TABLE `users` (
        `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
        `name` varchar(100) DEFAULT NULL,
        `phone` varchar(100) DEFAULT NULL,
        PRIMARY KEY (`id`)
      ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
      

      插入值语法:

      INSERT INTO `users` (`id`, `name`, `phone`)
      VALUES
          (1,'Sarah','12345'),
          (2,'John','67890');
      

      表值:

      id  name    phone
      -----------------
      1   Sarah   12345
      2   John    67890
      

      这篇关于模拟 PDO 获取失败情况的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆