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

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

问题描述

符合php文档,PDO方法 fetch() 在没有发现记录 AND 时返回值 FALSE (例如,假设数据库访问有问题)。



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

  PDO :: ATTR_ERRMODE => PDO :: ERRMODE_EXCEPTION 

我需要一个案例,其中 fetch ()方法将抛出异常。为什么?因为我想检查,要确保$ code> fetch()在失败时抛出异常,并且不会返回 FALSE 失败。



如果是这种情况,那么我确实会考虑 FALSE 返回由于没有在db表中找到任何记录,因此 fetch()



我的问题是:您是否知道一种模拟 fetch()方法的失败情况的方法?



谢谢。



PS :我的问题的答案将帮助我找到我的另一个问题的答案:当没有找到记录时,PHP PDO fetch返回FALSE失败






编辑1:



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

 <?php 

//激活错误报告。
error_reporting(E_ALL);
ini_set('display_errors',1);

尝试{

//创建一个PDO实例作为数据库连接到MySQL数据库。
$ 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

);

//定义sql语句。
$ sql ='SELECT * FROM users WHERE name =:name';

/ *
*准备并验证sql语句。
*
* ---------------------------------------- ----------------------------------------
*如果数据库服务器不能成功准备语句,PDO :: prepare()
*返回FALSE或发出PDOException(取决于错误处理设置)。
* --------------------------------------------- -----------------------------------
* /
$ statement = $ connection - >制备($ SQL);

if(!$ statement){
throw new UnexpectedValueException('sql语句无法准备好!
}

//将输入参数绑定到准备好的语句中。
$ bound = $ statement-> bindValue(':name','Sarah',PDO :: PARAM_STR);

//验证输入参数的绑定。
if(!$ bound){
throw new UnexpectedValueException('一个输入参数不能绑定!
}

/ *
*执行准备好的语句。
*
* ---------------------------------------- --------------------------
* PDOStatement :: execute在成功时返回TRUE,失败时返回FALSE。
* --------------------------------------------- ---------------------
* /
$ executed = $ statement-> execute();

如果(!$执行){
throw new UnexpectedValueException('准备好的语句不能执行!
}

/ *
*获取并验证结果集。
*
* ==================================== =================
*注:
* =================== ==================================
* PDOStatement :: fetch不仅返回FALSE失败,
*,但还没有找到记录!
*
*相反,PDOStatement :: fetchAll在失败时返回FALSE,
*,但如果没有找到记录,则返回一个空数组。这是
*自然,期望的行为。
* ========================================= ============
* /
$ resultset = $ statement-> fetch(PDO :: FETCH_ASSOC);

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

//显示结果集。
var_dump($ resultset);
echo'< pre>'。 print_r($ resultset,TRUE)。 < /预>;

//关闭连接。
$ connection = NULL;
} catch(PDOException $ exc){
echo'< pre>'。 print_r($ exc,TRUE)。 < /预>;
exit();
} catch(异常$ exc){
echo'< pre>'。 print_r($ exc,TRUE)。 < /预>;
exit();
}

我使用以下创建表语法:

  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名称
--------
1 Sarah
2 John
pre>

解决方案

最后,我发现一个案例,允许我测试,如果 PDOStatement :: fetch 确实会在失败时引起异常。



Credits:



一个href =http://dev.linguisticteam.org/2015/04/pdo-fetch-modes/ =nofollow noreferrer>利用PDO的提取模式呈现这种情况。它基于使用 PDOStatement :: fetchAll PDO :: FETCH_KEY_PAIR 常量作为参数传递。



测试:



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


SQLSTATE [HY000]:常规错误:PDO :: FETCH_KEY_PAIR提取模式
要求结果集包含最多2列。




结论:




  • PDOStatement :: fetch 返回 FALSE ,如果没有记录。

  • PDOStatement :: fetch throws - 确实是失败的例外。



注意:





PS:



我想要感谢所有尝试帮助我找到我的问题的答案的用户。你有我的感谢!






用于测试的代码:



 <?php 

//激活错误报告。
error_reporting(E_ALL);
ini_set('display_errors',1);

尝试{

//创建一个PDO实例作为数据库连接到MySQL数据库。
$ 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

);

//定义sql语句。
$ sql ='SELECT * FROM users WHERE name =:name';

/ *
*准备sql语句。
*
* ---------------------------------------- ----------------------------------------
*如果数据库服务器不能成功准备语句,PDO :: prepare()
*返回FALSE或发出PDOException(取决于错误处理设置)。
* --------------------------------------------- -----------------------------------
* /
$ statement = $ connection - >制备($ SQL);

//验证sql语句的准备。
if(!$ statement){
throw new UnexpectedValueException('sql语句无法准备!
}

//将输入参数绑定到准备好的语句中。
$ bound = $ statement-> bindValue(':name','Sarah',PDO :: PARAM_STR);

//验证输入参数的绑定。
if(!$ bound){
throw new UnexpectedValueException('一个输入参数不能绑定!
}

/ *
*执行准备好的语句。
*
* ---------------------------------------- --------------------------
* PDOStatement :: execute在成功时返回TRUE,失败时返回FALSE。
* --------------------------------------------- ---------------------
* /
$ executed = $ statement-> execute();

//验证准备好的语句的执行。
如果(!$执行){
throw new UnexpectedValueException('准备好的语句不能执行!
}

//获取结果集。
$ resultset = $ statement-> fetch(PDO :: FETCH_KEY_PAIR);

//如果找不到记录,将结果集定义为空数组。
if($ resultset === FALSE){
$ resultset = [];
}

//显示结果集。
var_dump($ resultset);

//关闭连接。
$ connection = NULL;
} catch(PDOException $ exc){
echo'< pre>'。 print_r($ exc-> getMessage(),TRUE)。 < /预>;
exit();
} catch(异常$ exc){
echo'< pre>'。 print_r($ exc-> getMessage(),TRUE)。 < /预>;
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, '约翰', '67890');



表格值:



  id name phone 
-----------------
1莎拉12345
2约翰67890


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).

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

PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION

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.

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.

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

Thank you.

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


Edit 1:

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;

and the following table values:

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

So, the table looks like this:

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

解决方案

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

Credits:

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.

Test:

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]: General error: PDO::FETCH_KEY_PAIR fetch mode requires the result set to contain extactly 2 columns.

Conclusion:

  • PDOStatement::fetch returns FALSE, if no records are found.
  • PDOStatement::fetch throws - indeed - an exception in case of failure.

Notes:

  • 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.

P.S:

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


The code used for testing:

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

Create table syntax:

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 values syntax:

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

Table values:

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

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

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