PDO连接测试

46
我正在为我的一个应用程序编写安装程序,我想测试一些默认的数据库设置。使用PDO测试有效和无效的数据库连接是否可行?
我有以下代码:
try{
            $dbh = new pdo('mysql:host=127.0.0.1:3308;dbname=axpdb','admin','1234');
            die(json_encode(array('outcome' => true)));
        }catch(PDOException $ex){
            die(json_encode(array(
                'outcome' => false,
                'message' => 'Unable to connect'
            )));
        }
我遇到的问题是脚本会在执行时间达到60秒时才停止尝试连接,而不是显示无法连接到数据库。
谢谢。

$dbh = new PDO?对我来说其他的看起来都很好。 - Sascha Galley
小写的PDO与PDO的工作方式相同,如果我在脚本中放入正确的详细信息,则可以正常工作,但我正在尝试检测无效的设置。 - Lee
你尝试添加选项 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION 了吗? - Sascha Galley
如果我在这里添加:$dbh = new PDO('mysql:host=127.0.0.1;port=3308;dbname=axpdb','admin','1234', array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));,它没有任何区别,因为正是这行代码出错了,所以我无法在下面执行$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); - Lee
4个回答

64

连接数据库时,您需要设置错误模式:

try{
    $dbh = new pdo( 'mysql:host=127.0.0.1:3308;dbname=axpdb',
                    'admin',
                    '1234',
                    array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
    die(json_encode(array('outcome' => true)));
}
catch(PDOException $ex){
    die(json_encode(array('outcome' => false, 'message' => 'Unable to connect')));
}

更多信息请参见以下链接:

使用PDO连接MySQL

错误和错误处理


1
那个加上 ini_set('display_errors', 'off'); 就可以了。谢谢 - Lee
5
为什么需要关闭显示错误?你已经捕获了异常——它已经被处理了。 - mpen
1
@Mark,因为PDO::ERRMODE_EXCEPTION的实现有问题(PHP5.3.28),在某些情况下没有效果(例如,在我的主机上,“DB服务器未运行”)。所以,这个解决方案不够完美,正如Themodem在他的解决方法中指出的那样。 (顺便说一句,只需使用@new pdo(),不要强制将display_errors设置为off!) - Sz.
警告:PDO::__construct() [pdo.--construct]:[2002] 无法建立连接,因为目标计算机积极拒绝了连接。 (尝试通过tcp://localhost:3306连接)...,代码为:$ this->pdo = new PDO($ cfg ['DB'],$ cfg ['DB_USER'],$ cfg ['DB_PASS'],array(PDO :: ATTR_ERRMODE => PDO :: ERRMODE_EXCEPTION, PDO :: MYSQL_ATTR_LOCAL_INFILE => true));(注意:异常确实被抛出并捕获,我在catch子句中放置了一些日志消息。) - Sz.

10

正如 @Sascha Galley 提到的,你应该将错误模式设置为异常模式。然而,在某些情况下,您还应设置 PDO::ATTR_TIMEOUT 属性,以防止长时间等待响应。

尽管文档表示此属性的行为取决于驱动程序,在 MySQL 的情况下它是连接超时。在文档中找不到有关它的任何信息,但这里是来自驱动程序源代码的简短片段:

long connect_timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, 30 TSRMLS_CC);

2

正如在这个答案的评论中所看到的(但几乎没有其他地方,因此我在这里将其更加明显),"经典"的PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION 解决方案并不总是有效

实现PDO :: ERRMODE_EXCEPTION 存在问题,因此在某些情况下似乎会出现泄漏。

例如:

警告:PDO::__construct() [pdo.--construct]:[2002]无法建立连接,因为目标计算机积极拒绝 它。 (尝试通过tcp:// localhost:3306连接)在 [...] db.php 34

代码:

try {
    $this->pdo = new PDO($cfg['DB'], $cfg['DB_USER'], $cfg['DB_PASS'],
        array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
} catch {
    echo("Can't open the database.");
}

异常被抛出并捕获(我可以看到我的消息)。

因此,作为必要的解决方法,您需要在new pdo(...)之前也加上一个@(在这种情况下,让我们称其为“尿布操作符”)以确保代码的干净。


不建议抑制错误,因为这可能会导致程序行为异常,而没有清楚地通知您问题所在。 请访问https://www.sitepoint.com/why-suppressing-notices-is-wrong/获取更多信息。 - Kalema Edgar
@KalemaEdgar,一般来说是这样的。但您似乎忽略了“PDO::ERRMODE_EXCEPTION实现有问题”的部分。这是一个特殊情况。 (该错误报告似乎仍然未关闭,但我最近几年没有使用过PDO,也许它已不再失败。) - Sz.

1
在PDO::ERRMODE_EXCEPTION的结尾缺少一个闭合括号。

应该是:

$this->pdo = new PDO($cfg['DB'], $cfg['DB_USER'], $cfg['DB_PASS'],
    array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接