模拟 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::fetchAll
和 PDO::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
在失败的情况下抛出 - 实际上 - 一个异常.PDOStatement::fetch
returnsFALSE
, 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.
Conclusion:
我要感谢所有试图帮助我找到问题答案的用户.你有我的感激之情!
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
相关文章