©
Dokumen ini menggunakan Manual laman web PHP Cina Lepaskan
连接是通过创建 PDO 基类的实例而建立的。不管使用哪种驱动程序,都是用 PDO 类名。构造函数接收用于指定数据库源(所谓的 DSN)以及可能还包括用户名和密码(如果有的话)的参数。
Example #1 连接到 MySQL
<?php
$dbh = new PDO ( 'mysql:host=localhost;dbname=test' , $user , $pass );
?>
如果有任何连接错误,将抛出一个 PDOException 异常对象。如果想处理错误状态,可以捕获异常,或者选择留给通过 set_exception_handler() 设置的应用程序全局异常处理程序。
Example #2 处理连接错误
<?php
try {
$dbh = new PDO ( 'mysql:host=localhost;dbname=test' , $user , $pass );
foreach( $dbh -> query ( 'SELECT * from FOO' ) as $row ) {
print_r ( $row );
}
$dbh = null ;
} catch ( PDOException $e ) {
print "Error!: " . $e -> getMessage () . "<br/>" ;
die();
}
?>
如果应用程序不在 PDO 构造函数中捕获异常,zend 引擎采取的默认动作是结束脚本并显示一个回溯跟踪,此回溯跟踪可能泄漏完整的数据库连接细节,包括用户名和密码。因此有责任去显式(通过 catch 语句)或隐式(通过 set_exception_handler() )地捕获异常。
连接数据成功后,返回一个 PDO 类的实例给脚本,此连接在 PDO 对象的生存周期中保持活动。要想关闭连接,需要销毁对象以确保所有剩余到它的引用都被删除,可以赋一个 NULL
值给对象变量。如果不明确地这么做,PHP 在脚本结束时会自动关闭连接。
Example #3 关闭一个连接
<?php
$dbh = new PDO ( 'mysql:host=localhost;dbname=test' , $user , $pass );
// 在此使用连接
// 现在运行完成,在此关闭连接
$dbh = null ;
?>
很多 web 应用程序通过使用到数据库服务的持久连接获得好处。持久连接在脚本结束后不会被关闭,且被缓存,当另一个使用相同凭证的脚本连接请求时被重用。持久连接缓存可以避免每次脚本需要与数据库回话时建立一个新连接的开销,从而让 web 应用程序更快。
Example #4 持久化连接
<?php
$dbh = new PDO ( 'mysql:host=localhost;dbname=test' , $user , $pass , array(
PDO :: ATTR_PERSISTENT => true
));
?>
Note:
如果想使用持久连接,必须在传递给 PDO 构造函数的驱动选项数组中设置
PDO::ATTR_PERSISTENT
。如果是在对象初始化之后用 PDO::setAttribute() 设置此属性,则驱动程序将不会使用持久连接。
Note:
如果使用 PDO ODBC 驱动且 ODBC 库支持 ODBC 连接池(有unixODBC 和 Windows 两种做法;可能会有更多),建议不要使用持久的 PDO 连接,而是把连接缓存留给 ODBC 连接池层处理。 ODBC 连接池在进程中与其他模块共享;如果要求 PDO 缓存连接,则此连接绝不会被返回到 ODBC 连接池,导致创建额外的连接来服务其他模块。
[#1] ogierschelvis at gmail dot com [2015-11-25 13:55:41]
As http://stackoverflow.com/questions/17630772/pdo-cannot-connect-remote-mysql-server points out; sometimes when you want to connect to an external server like this:
<?php
$conn = new PDO('mysql:host=123.4.5.6;dbname=test_db;port=3306','username','password');
?>
it will fail no matter what. However if you put a space between mysql: and host like this:
<?php
$conn = new PDO('mysql: host=123.4.5.6;dbname=test_db;port=3306','username','password');
?>
it will magically work. I'm not sure if this applies in all cases or server setups. But I think it's worth mentioning in the docs.
[#2] edsanhu at gmail dot com [2015-11-06 10:50:07]
For being able to retrieve information from the db in utf-8 the connection assignment has to add to the dsn `charset=utf8`:
<?php
$dbh = new PDO('mysql:host=localhost;dbname=test;charset=utf8', $user, $pass);
?>
[#3] Vicente [2014-06-19 08:48:51]
WARNING: please note that the documentation is FALSE and INCOMPLETE, when it states setting the variable to NULL is enough to close the connection. Unfortunately, the real signification is obscur for those who don't understand what it means setting a variable to NULL in PHP (ref count).
In fact, references count is used to determine automatically when a connection must be closed: when the connection instance is not holded by any variable anymore, it is closed. Not very flexible to manage resources allocation exactly the way you want.
PDO class actually doesn't expose any method to manually close connection it opens in the constructor.
[#4] cappytoi at yahoo dot com [2014-04-09 19:08:21]
Using PHP 5.4.26, pdo_pgsql with libpg 9.2.8 (self compiled). As usual PHP never explains some critical stuff in documentation. You shouldn't expect that your connection is closed when you set $dbh = null unless all you do is just instantiating PDO class. Try following:
<?php
$pdo = new PDO('pgsql:host=192.168.137.1;port=5432;dbname=anydb', 'anyuser', 'pw');
sleep(5);
$stmt = $pdo->prepare('SELECT * FROM sometable');
$stmt->execute();
$pdo = null;
sleep(60);
?>
Now check your database. And what a surprise! Your connection hangs for another 60 seconds. Now that might be expectable because you haven't cleared the resultset.
<?php
$pdo = new PDO('pgsql:host=192.168.137.160;port=5432;dbname=platin', 'cappytoi', '1111');
sleep(5);
$stmt = $pdo->prepare('SELECT * FROM admin');
$stmt->execute();
$stmt->closeCursor();
$pdo = null;
sleep(60);
?>
What teh heck you say at this point? Still same? Here is what you need to do to close that connection:
<?php
$pdo = new PDO('pgsql:host=192.168.137.160;port=5432;dbname=platin', 'cappytoi', '1111');
sleep(5);
$stmt = $pdo->prepare('SELECT * FROM admin');
$stmt->execute();
$stmt->closeCursor(); // this is not even required
$stmt = null; // doing this is mandatory for connection to get closed
$pdo = null;
sleep(60);
?>
PDO is just one of a kind because it saves you to depend on 3rd party abstraction layers. But it becomes annoying to see there is no implementation of a "disconnect" method even though there is a request for it for 2 years. Developers underestimate the requirement of such a method. First of all, doing $stmt = null everywhere is annoying and what is most annoying is you cannot forcibly disconnect even when you set $pdo = null. It might get cleared on script's termination but this is not always possible because script termination may delayed due to slow client connection etc.
Anyway here is how to disconnect forcibly using postgresql:
<?php
$pdo = new PDO('pgsql:host=192.168.137.160;port=5432;dbname=platin', 'cappytoi', '1111');
sleep(5);
$stmt = $pdo->prepare('SELECT * FROM admin');
$stmt->execute();
$pdo->query('SELECT pg_terminate_backend(pg_backend_pid());');
$pdo = null;
sleep(60);
?>
Following may be used for MYSQL: (not guaranteed)
KILL CONNECTION_ID()
[#5] jgestiotremovethis at gmail dot com [2014-03-31 22:47:34]
Most web development does not warrant the use of Object Oriented Programming so it is surprising to see interfaces such as PDO are only provided as a class. The language should not force the developers to adopt Object Oriented Programming if they do not wish to use it.
[#6] thz at plista dot com [2013-06-14 13:27:53]
If you are using PHP 5.4 and later, you can no longer use persistent connections when you have your own database class that derives from the native PDO object. If you do, you will get segmentation faults during the PHP process shutdown.
Please see this bug report for more information: https://bugs.php.net/bug.php?id=63176
[#7] alvaro at demogracia dot com [2011-07-01 10:07:04]
On connection errors, the PDO constructor seems to do two things no matter your PDO::ATTR_ERRMODE setting:
1. Trigger a warning
2. Throw a PDOException
If you set the PDO::ATTR_ERRMODE parameter, it will only take effect on further operations.
[#8] jak dot spalding at gmail dot com [2011-04-10 12:35:22]
Just thought I'd add in and give an explanation as to why you need to use 127.0.0.1 if you have a different port number.
The mysql libraries will automatically use Unix sockets if the host of "localhost" is used. To force TCP/IP you need to set an IP address.
[#9] angela [2010-04-06 02:53:09]
I spent hours today trying to get my portable wamp to update a database, using localhost:800 and port 3307 for mysql. For it to work I needed to adjust the connect() instruction as described:
$dsn = "mysql:host=127.0.0.1;port=3307;dbname=mydatabase";
[#10] neville at whitespacers dot com [2009-10-16 03:40:17]
To avoid exposing your connection details should you fail to remember to catch any exception thrown by the PDO constructor you can use the following class to implicitly change the exception handler temporarily.
<?php
Class SafePDO extends PDO {
public static function exception_handler($exception) {
// Output the exception details
die('Uncaught exception: ', $exception->getMessage());
}
public function __construct($dsn, $username='', $password='', $driver_options=array()) {
// Temporarily change the PHP exception handler while we . . .
set_exception_handler(array(__CLASS__, 'exception_handler'));
// . . . create a PDO object
parent::__construct($dsn, $username, $password, $driver_options);
// Change the exception handler back to whatever it was before
restore_exception_handler();
}
}
// Connect to the database with defined constants
$dbh = new SafePDO(PDO_DSN, PDO_USER, PDO_PASSWORD);
?>
[#11] dan dot franklin at pearson dot com [2008-04-17 09:37:23]
Note that you can specify a port number with "port=####", but this port number will be ignored if the host is localhost. If you want to connect to a local port other than the default, use host=127.0.0.1 instead of localhost.