|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2017-10-05 20:42 UTC] adambaratz@php.net
-Status: Open
+Status: Not a bug
[2017-10-05 20:42 UTC] adambaratz@php.net
[2017-10-05 21:34 UTC] nikic@php.net
[2017-10-05 23:20 UTC] ian at oshaughnessy dot cc
[2017-10-06 15:14 UTC] adambaratz@php.net
[2020-11-11 13:57 UTC] niklas dot brunberg at ateles dot se
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Wed Oct 29 14:00:01 2025 UTC |
Description: ------------ The only way to close a PDO connection is to set the resource variable to null (thereby destroying the PDO object); however, when extending the PdoStatement class, it's required that $this is passed as an option to the PDO object for Pdo::ATTR_STATEMENT_CLASS. In doing this, a reference to the PDO object is created, making it impossible to destroy the PDO object since a lingering reference continues to exist after $pdo is set to null. The only way to fix this issue is to use Pdo::setAttribute() after the PDO parent constructor has been run. Test script: --------------- <?php echo "Test 1 (PdoTestBroken)\n"; echo "new PdoTestBroken\n"; $pdo1 = new PdoTestBroken($dsn, $username, $password, []); echo "Destroy \$pdo\n"; $pdo1 = null; echo "----------------------------\n\n"; echo "Test 2 (PdoTestWorks)\n"; echo "new PdoTestWorks\n"; $pdo2 = new PdoTestWorks($dsn, $username, $password, []); echo "Destroy \$pdo\n"; $pdo2 = null; echo "----------------------------\n\n"; class PdoTestBroken extends Pdo { public function __construct($dsn, $username, $passwd, $options) { echo "PdoTest1::__construct()\n"; $options[self::ATTR_STATEMENT_CLASS] = [ 'PdoStatementTest', [ $this, ] ]; parent::__construct($dsn, $username, $passwd, $options); } public function __destruct() { echo "PdoTest1::__destruct()\n"; } } class PdoTestWorks extends Pdo { public function __construct($dsn, $username, $passwd, $options) { echo "PdoTest2::__construct()\n"; $self = parent::__construct($dsn, $username, $passwd, $options); $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, [ 'PdoStatementTest', [ $self, ] ]); } public function __destruct() { echo "PdoTest2::__destruct()\n"; } } class PdoStatementTest extends PdoStatement { } Expected result: ---------------- The connection to close. Actual result: -------------- The connection does not close due to hidden reference variable. Script Results: Test 1 (PdoTestBroken) new PdoTestBroken PdoTest1::__construct() Destroy $pdo ---------------------------- Test 2 (PdoTestWorks) new PdoTestWorks PdoTest2::__construct() Destroy $pdo PdoTest2::__destruct() ---------------------------- PdoTest1::__destruct()