Qui est le coupable ? PDO ou MySQLi ?

Eléphant du PHP | 65 Messages

09 juin 2016, 11:43

Bonjour à tous,

Code : Tout sélectionner

<?php abstract class DBFactory { private static $pdo; private static $mysqli; public static function getPDO() { if (!(self::$pdo instanceof PDO)): echo 'création d\'une instance de PDO<br />'; self::$pdo = new PDO('mysql:host=localhost;dbname=Test', 'user', 'pwd'); self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); endif; return self::$pdo; } public static function getMySQLi() { if (!(self::$mysqli instanceof MySQLi)): echo 'création d\'une instance de mysqli'; self::$mysqli = new mysqli('localhost', 'user', 'pwd', 'Test'); endif; return self::$mysqli; } public static function closePDO() { if (self::$pdo instanceof PDO): self::$pdo = null; endif; } public static function closeMySQLi() { if (self::$mysqli instanceof MySQLi): self::$mysqli->close(); self::$mysqli = null; endif; } public static function getStatus() { yield (self::$pdo instanceof PDO) . '<br />'; yield (self::$mysqli instanceof MySQLi) . '<br />'; return; } } echo "essai 1:<br />"; $pdo = DBFactory::getPDO(); $mysqli = DBFactory::getMySQLi(); var_dump($pdo, $mysqli); // "création d'une instance de PDO", "création d'une instance de mysqli" 2 objets ok echo 'status :<br />'; foreach(DBFactory::getStatus() as $status): echo $status; // pdo = 1, mysqli = 1 endforeach; echo "<br />essai 2:<br />"; $pdo = DBFactory::getPDO(); $mysqli = DBFactory::getMySQLi(); var_dump($pdo, $mysqli); // no soucy /** * sleep(10) à cet endroit: * mysql> SHOW PROCESSLIST; +-----+------+-----------------+------+---------+------+----------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +-----+------+-----------------+------+---------+------+----------+------------------+ | 139 | root | localhost:50218 | NULL | Query | 0 | starting | SHOW PROCESSLIST | | 144 | root | localhost:50226 | test | Sleep | 4 | | NULL | | 145 | root | localhost:50227 | test | Sleep | 4 | | NULL | +-----+------+-----------------+------+---------+------+----------+------------------+ * 2 connexions sont ouvertes (je compte pas le query...) **/ echo 'essai 3: fermeture des connexions'; DBFactory::closeMySQLi(); /** * sleep(10) à cet endroit: * mysql> SHOW PROCESSLIST; * +-----+------+-----------------+------+---------+------+----------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +-----+------+-----------------+------+---------+------+----------+------------------+ | 139 | root | localhost:50218 | NULL | Query | 0 | starting | SHOW PROCESSLIST | | 146 | root | localhost:50230 | test | Sleep | 3 | | NULL | +-----+------+-----------------+------+---------+------+----------+------------------+ * la connexion mysqli est bien fermée **/ DBFactory::closePDO(); /** * sleep(10) à cet endroit: * mysql> SHOW PROCESSLIST; * +-----+------+-----------------+------+---------+------+----------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +-----+------+-----------------+------+---------+------+----------+------------------+ | 139 | root | localhost:50218 | NULL | Query | 0 | starting | SHOW PROCESSLIST | | 148 | root | localhost:50235 | test | Sleep | 2 | | NULL | +-----+------+-----------------+------+---------+------+----------+------------------+ * la connexion PDO est toujours ouverte **/ var_dump($pdo, $mysqli); // pdo = object pdo, mysqli = Warning: var_dump(): Property access is not allowed yet in E:\... on line 76 echo 'status :<br />'; foreach(DBFactory::getStatus() as $status): echo $status; // pdo = null, mysqli = null endforeach; echo 'essai 4: ($pdo = null, $mysqli->close()):<br />'; $pdo = DBFactory::getPDO(); $mysqli = DBFactory::getMySQLi(); var_dump($pdo, $mysqli); // "création d'une instance de pdo", "creation d'une instance de mysqli"
Je voudrais comprendre pourquoi je choppe des warnings à cause de l'objet MySQLi ? D'après ce que j'ai compris, c'est à cause que la connexion à été effectivement fermée et visiblement il n'y a aucun moyen de fermer une connexion avec PDO.

Je sais que c'est un peu tiré par les cheveux mais j'aimerais bien comprendre :oops:

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

09 juin 2016, 13:06

Salut,

As tu les mêmes référence d'objet (pdo et mysqli) en mémoire (dans la classe et en dehors). tu peux voir cela en debug.

La connexion ouverte par PDO doit s'expliquer simplement par le fait quand tant que le GC n'est pas passé l'objet est toujours en mémoire donc la connexion toujours active.
La connexion avec mysqli est fermée parce que l'on peux lui dire.

Pour l'erreur je dirais que la variable mysql est une référence vers la private de l'objet, vu qu'elle est nul boom (non trouvé dans l'objet).
Cela semble capillotracté mais vraisemblable quand même.
pour être certain il faut un debug, un point d'arrêt avant le var_dump et tu compare ce qu'il y a dans l'objet et la variable $mysql


@+
Il en faut peu pour être heureux ......