Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 模拟PDO获取失败的情况_Php_Mysql_Pdo_Exception Handling_Fetch - Fatal编程技术网

Php 模拟PDO获取失败的情况

Php 模拟PDO获取失败的情况,php,mysql,pdo,exception-handling,fetch,Php,Mysql,Pdo,Exception Handling,Fetch,根据php文档,PDO方法在未找到任何记录时返回值FALSE,在失败时返回值(例如,当数据库访问出现问题时) 假设我将PHP错误报告系统设置为在失败时抛出异常: PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION 我需要一个案例,即fetch()方法将抛出异常的情况。为什么?因为我想检查,100%确保fetch()在失败时抛出异常,而不是在失败时返回FALSE 如果是这样的话,那么我确实会考虑 > FETCH()/中返回的错误/代码>,因为在DB表中没

根据php文档,PDO方法在未找到任何记录时返回值
FALSE
,在失败时返回值(例如,当数据库访问出现问题时)

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

PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
我需要一个案例,即
fetch()
方法将抛出异常的情况。为什么?因为我想检查,100%确保
fetch()
在失败时抛出异常,而不是在失败时返回
FALSE

如果是这样的话,那么我确实会考虑<代码> > FETCH()/<代码>中返回的<代码>错误/代码>,因为在DB表中没有找到任何记录。

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

多谢各位

p.S.:我的问题的答案将帮助我找到其他问题的答案:


编辑1:

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

<?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();
}
以及下表中的值:

$sql  = 'SELECT * FROM users WHERE name = :name';
$stmt = $connection->prepare($sql);
$stmt->bindValue(':name', 'Sarah');
$executed = $stmt->execute();

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

$result_set = fetch($stmt);
if ($result_set === false) {
    throw new UnexpectedValueException('Fetching data failed!');
}
// handle result set
因此,该表如下所示:

<?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();
}

除非循环需要PDO语句,否则可以在方法/函数中使用fetchAll来获得所需的结果。只需执行fetchAll而不是fetch,检查false,并根据需要返回。在这种情况下,您的查询应该确保只返回1行

像这样的东西

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;
请注意,fetchColumn也有类似的问题

以上内容将返回

  • 查询失败时为false
  • 如果找不到行,则获取空数组
  • 如果找到,则获取相应的结果集
  • 如果找不到fetchColumn,则为null
  • fetchColumn的列值(如果找到)
扫描您的代码样本,您可以这样实现

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

您还可以做更多的工作来改进上述内容,但希望您能理解。

使用
PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION
fetch在出现错误时始终会抛出异常。你可以在你的catch块中处理它们,它返回什么并不重要。因此,如果您没有捕获到异常,并且它返回false,那么您可以安全地假定它是由于一个空集引起的。这是处理PDO错误的一种非常有效的方法。要回答您的问题,有许多方法可以模拟错误。最基本的是不正确的查询语法。您还可以尝试绑定不存在的参数、绑定错误数量的参数等。使用此方案的时间越长,您将看到越多类型的错误/异常。它非常有效,因为每个错误都包含一条详细的消息来帮助您调试它。

最后,我发现了一个案例,它允许我测试
PDOStatement::fetch
是否确实会在失败时引发异常

信用: 文章提出了这样一种情况。它基于使用
PDOStatement::fetchAll
和作为参数传递的
PDO::FETCH_KEY_PAIR
常量

测试: 所以,我自己做了一个测试。但是我使用了
PDOStatement::fetch
方法。根据定义,
PDO::FETCH_KEY_PAIR
常量要求数据源表仅包含两列。在我的测试中,我定义了三个表列
PDOStatement::fetch
已将此情况识别为失败,并引发异常:

SQLSTATE[HY000]:一般错误:PDO::FETCH_KEY_PAIR FETCH模式 要求结果集包含extactly 2列

结论:
  • PDOStatement::fetch
    如果未找到任何记录,则返回
    FALSE
  • PDOStatement::fetch
    确实会在失败时抛出异常。
笔记:
  • 相反,
    PDOStatement::fetchAll
    如果找不到任何记录,则返回一个空数组
  • 官方页面上没有记录
    PDO::FETCH_KEY_PAIR
    常量
附笔: 我要感谢所有试图帮助我找到问题答案的用户。我很感激你


用于测试的代码: 插入值语法: 表值:
启用基于异常的错误报告手册中说:“此函数在成功时的返回值取决于获取类型。在所有情况下,失败时返回FALSE。”。当没有结果时,我希望它返回
NULL
。所以有两种不同的测试是可能的:
if($result==FALSE)
测试失败,
if(!isset($result))..
if(is_null($result))
测试没有记录。谢谢,@teresko。我已经有了。但是,由于php.net说,失败时返回FALSE,我真的不知道是否在失败时引发异常,而不是FALSE。在这种情况下,处理异常是一种方法。试试看。它会起作用的。@MasivuyeCokile我终于找到了一个案例,它允许我模拟
PDOStatement::fetch()
的失败情况。我贴出了答案。再次感谢您的评论!你的帖子没有回答这个问题,也没有回答之前的问题。我的帖子是回应他在上面问题中的评论。具体来说,他最后做的两个。@user2430012非常感谢您的回答!在<代码> FETCH()/代码>问题(以及我最后2个评论)中,我个人认为您的答案是符合条件的。@ USER 24012现在,基于我的问题的第三个版本:我倾向于99%考虑,在<代码> FET()的情况下,没有失败的情况。:-)我非常感谢你给我一个好答案!不客气。要添加,无论使用什么PDO::ATTR_ERRMOD,fetch()都不会引发异常。失败时它总是返回false。即使将stmt包装在try/catch块中,并在之后调用fetch(),它也会
$sql  = 'SELECT * FROM users WHERE name = :name';
$stmt = $connection->prepare($sql);
$stmt->bindValue(':name', 'Sarah');
$executed = $stmt->execute();

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

$result_set = fetch($stmt);
if ($result_set === false) {
    throw new UnexpectedValueException('Fetching data failed!');
}
// handle result set
<?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