我是PHP高级的新手。但对编程来说并不陌生。
我们有一个软件(正在解散但仍处于活动状态(正在杀死我们的数据库。
里面是用PDO的,经过大量花费时间的问题是PDO断开连接模式和在包装类中使用PDO的
。public function connect() {
if(!$this->connected){
$col = 'mysql:host='
.$this->parametri->getHOST()
.';'
.'dbname='
.$this->parametri->getDB()
.';'
.'charset=utf8';
try {
// connessione tramite creazione di un oggetto PDO
$db = new PDO($col , $this->parametri->getDBUSER(),
$this->parametri->getPASS());
$this->pdoconn=$db;
$this->connected=TRUE;
}
catch(PDOException $e) {
$this->connected=FALSE;
return NULL;
}
}
return $this->pdoconn;
}
public function getPDO(){
if ($this->connected){
return $this->pdoconn;
}else {
return NULL;
}
}
public function disconnect() {
$this->pdoconn=null;
$this->connected=FALSE;
}
阅读官方网站上的PDO文档和评论,当$this->pdoconn=null时,连接被释放;但它已经通过 getPDO(( 传递。
根据这篇文章和这个论述,某处可能有一个变量指向连接,所以连接永远不会被释放;类认为连接被释放了,当请求创建一个新连接时,最后一个连接会丢失给类的用户。
所以这个想法是传回连接 tu null 也这样,或者还有另一种方法来保护 pdoconn 并强制为空。
public function disconnect(&$var) {
$var=null;
$this->pdoconn=null;
$this->connected=FALSE;
}
另一种方法是构建另一个永远不会公开 pdo conn 的包装类,并强制在其中执行查询以管理断开连接。
也许尝试将连接和/或类设置为singleton
,然后它应该保留数据库连接,每次使用它时,它都将是相同的连接。如果这样做,则不必在每次使用连接时都专注于关闭连接,因为整个页面只有一个连接。下面是一个简单的示例:
class MyClass
{
// You can make the class itself persist to save on resources
private static $obj;
// You can save the connection specifically to reuse it
private static $singleton;
// Return itself to static var
public function __construct()
{
if(!empty(self::$obj)) {
echo 'OLD OBJ<br />';
return self::$obj;
}
echo 'NEW OBJ<br />';
self::$obj = $this;
return self::$obj;
}
// Return connection if already set
public function connect($username = "username",$password = "password",$host = "host",$database = "dbname")
{
if(!empty(self::$singleton)) {
echo 'OLD CONN<br />';
return self::$singleton;
}
try {
self::$singleton = new PDO('mysql:host='.$host.';dbname='.$database.';charset=utf8',$username,$password);
}
catch(PDOException $e) {
die('connection failed');
}
echo 'NEW CONN<br />';
return self::$singleton;
}
}
使用示例:
// Creates first PDO connection
$database = new MyClass();
$con1 = $database->connect();
function getConnection()
{
// Creates first connection
$database = new MyClass();
return $database->connect();
}
// Won't create a new instance, but rather use the same.
$con2 = getConnection();
会写:
NEW OBJ
NEW CONN
OLD OBJ
OLD CONN
这是我实现单例数据库实例以保持持久数据库连接的方式:
class DB implements IConnectInfo {
public static function factory() {
if( self::$_instance === null ) {
self::$_instance = new DB( 'HOST', 'USERNAME', 'PASSWORD', 'DATABASE' );
}
return self::$_instance;
}
protected function __construct( $host, $username, $password, $database ) {
try {
$this->_link = new PDO( "mysql:host={$host};dbname={$database}", $username, $password, array( PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8" ) );
$this->_link->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$this->_link->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch(PDOException $e) {
$this->_link = null;
die( "ERROR: Could not connect to the database" );
}
}
public function __destruct() {
if ( $this->_hasActiveTransaction ) {
$this->commit();
}
}
final private function __clone() {
}
public function &link() {
return $this->_link;
}
public function beginTransaction() {
if ( $this->_hasActiveTransaction == false ) {
try {
$this->_link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->_link->beginTransaction();
$this->_hasActiveTransaction = true;
return true;
} catch (PDOException $e) {
error_log($e);
die();
return false;
}
}
return true;
}
public function rollBack() {
if( !$this->beginTransaction() ) {
return false;
}
try {
$this->_link->rollBack();
$this->_hasActiveTransaction = false;
return true;
} catch (PDOException $e) {
error_log($e);
return false;
}
}
public function commit() {
if( !$this->beginTransaction() ) {
return false;
}
try {
$this->_link->commit();
$this->_hasActiveTransaction = false;
return true;
} catch (PDOException $e) {
$this->rollBack();
return false;
}
}
private $_hasActiveTransaction = false;
private $_result = null;
private $_link = null;
static private $_instance = null;
}
然后我像这样使用它:
$DB = DB::factory();
$query = "SELECT * FROM myTable";
$stmt = $DB->link()->prepare( $query );
$stmt->execute();
while( $myTableObj = $stmt->fetch( PDO::FETCH_OBJ ) ) {
echo $myTableObj->myField
}