Я новичок в PHP высокого уровня. Но не новичок в программировании.
У нас есть программное обеспечение (находящееся в процессе ликвидации, но все еще активное), которое убивает нашу БД.
Внутри используется PDO, проблема после большого количества потраченного времени — режим отключения PDO и использование PDO внутри класса Wrap.
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 ().
В соответствии с Эта статья а также это диссертация, где-то может быть переменная, указывающая на соединение, поэтому соединение никогда не освобождается; класс думает, что соединение освобождено, и когда запрос создает новое соединение, теряет последнее для пользователя класса.
Таким образом, идея состоит в том, чтобы вернуть соединение обратно null, также это или есть другой способ защитить pdoconn и заставить быть нулевым.
public function disconnect(&$var) {
$var=null;
$this->pdoconn=null;
$this->connected=FALSE;
}
Другой способ — создать еще один класс wrap, который никогда не выставляет 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
}