From 2c150f503b7d5894eb091b10bf6c30974f9a7028 Mon Sep 17 00:00:00 2001 From: Alexandru Benzari Date: Thu, 27 Aug 2026 18:58:54 +0100 Subject: [PATCH] Fix PHP 8.5 PDO deprecations, keep compatibility with older PHP PHP 8.5 deprecates driver-specific constants defined on the base PDO class in favor of the Pdo\ subclasses added in PHP 8.4. Resolve PDO::MYSQL_ATTR_USE_BUFFERED_QUERY and DSN fragment option constants (eg. MYSQL_ATTR_INIT_COMMAND) conditionally so the library keeps working unchanged on PHP < 8.4 while avoiding the new deprecation notices. Also add #[AllowDynamicProperties] to several classes that were still missing it, which have been raising dynamic-property deprecations since PHP 8.2. --- PDO/DataObject.php | 40 ++++++++++++++++++++++++++--- PDO/DataObject/Cast.php | 1 + PDO/DataObject/Exception.php | 1 + PDO/DataObject/Generator/Column.php | 1 + PDO/DataObject/Generator/Table.php | 1 + PDO/DataObject/Introspection.php | 1 + PDO/DataObject/Join.php | 1 + PDO/DataObject/Links.php | 3 ++- PDO/DataObject/Validate.php | 1 + tests/37-buffered.phpt | 6 ++++- tests/includes/PDO_Dummy.php | 10 ++++++-- 11 files changed, 59 insertions(+), 7 deletions(-) diff --git a/PDO/DataObject.php b/PDO/DataObject.php index 2c59c23b..27a138a5 100755 --- a/PDO/DataObject.php +++ b/PDO/DataObject.php @@ -606,10 +606,9 @@ final function PDO() $opts = array(); if (!empty($dsn_ar['fragment'])) { // options.. |MYSQL_ATTR_INIT_COMMAND=....| - $pdo_rc = new ReflectionClass( "PDO" ); foreach(explode('|', $dsn_ar['fragment']) as $opt) { list($k,$v) = explode('=', $opt); - $opts[$pdo_rc->getConstant($k)] = $v; + $opts[self::dsnOptionConstant($k)] = $v; } } @@ -654,6 +653,35 @@ final function PDO() return self::$connections[$md5]; } + /** + * Resolve a PDO option constant by name, as used in DSN fragment options + * (eg. |MYSQL_ATTR_INIT_COMMAND=...|). + * + * Driver-specific constants (MYSQL_*, PGSQL_*, SQLITE_*, OCI_*, ODBC_*, DBLIB_*, FIREBIRD_*) + * are deprecated on the base PDO class since PHP 8.5 - resolve them via the Pdo\ + * subclasses (available since PHP 8.4) when possible, falling back to the PDO class + * for generic constants and on older PHP versions. + */ + private static function dsnOptionConstant($name) + { + static $driverClasses = array( + 'MYSQL' => 'Pdo\\Mysql', + 'PGSQL' => 'Pdo\\Pgsql', + 'SQLITE' => 'Pdo\\Sqlite', + 'OCI' => 'Pdo\\Oci', + 'ODBC' => 'Pdo\\Odbc', + 'DBLIB' => 'Pdo\\Dblib', + 'FIREBIRD' => 'Pdo\\Firebird', + ); + + foreach ($driverClasses as $prefix => $class) { + if (strpos($name, $prefix . '_') === 0 && defined($class . '::' . $name)) { + return constant($class . '::' . $name); + } + } + + return defined('PDO::' . $name) ? constant('PDO::' . $name) : false; + } @@ -3378,9 +3406,15 @@ final function query($string) return $this->raise("Could not run Query: " . $result->getMessage(), self::ERROR_QUERY, $result); } + // PDO::MYSQL_ATTR_USE_BUFFERED_QUERY is deprecated since PHP 8.5 in favor of + // Pdo\Mysql::ATTR_USE_BUFFERED_QUERY (only available from PHP 8.4 onwards). + $mysqlAttrUseBufferedQuery = defined('Pdo\\Mysql::ATTR_USE_BUFFERED_QUERY') + ? constant('Pdo\\Mysql::ATTR_USE_BUFFERED_QUERY') + : PDO::MYSQL_ATTR_USE_BUFFERED_QUERY; + switch (true) { case $dbtype == 'sqlite': - case $pdo->getAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY) == 0: + case $pdo->getAttribute($mysqlAttrUseBufferedQuery) == 0: $no_results = true; break; diff --git a/PDO/DataObject/Cast.php b/PDO/DataObject/Cast.php index 70a28c5d..8f7fe961 100755 --- a/PDO/DataObject/Cast.php +++ b/PDO/DataObject/Cast.php @@ -61,6 +61,7 @@ * */ +#[AllowDynamicProperties] class PDO_DataObject_Cast { /** diff --git a/PDO/DataObject/Exception.php b/PDO/DataObject/Exception.php index 2cacf285..2b3d3c0b 100755 --- a/PDO/DataObject/Exception.php +++ b/PDO/DataObject/Exception.php @@ -23,6 +23,7 @@ */ +#[AllowDynamicProperties] class PDO_DataObject_Exception extends Exception { diff --git a/PDO/DataObject/Generator/Column.php b/PDO/DataObject/Generator/Column.php index 6c94a66e..d33ba125 100644 --- a/PDO/DataObject/Generator/Column.php +++ b/PDO/DataObject/Generator/Column.php @@ -28,6 +28,7 @@ * @version 1.0 * @link https://github.com/roojs/PDO_DataObject */ +#[AllowDynamicProperties] class PDO_DataObject_Generator_Column { diff --git a/PDO/DataObject/Generator/Table.php b/PDO/DataObject/Generator/Table.php index e692212f..78131a35 100644 --- a/PDO/DataObject/Generator/Table.php +++ b/PDO/DataObject/Generator/Table.php @@ -29,6 +29,7 @@ * @link https://github.com/roojs/PDO_DataObject */ +#[AllowDynamicProperties] class PDO_DataObject_Generator_Table { /** diff --git a/PDO/DataObject/Introspection.php b/PDO/DataObject/Introspection.php index 89377f78..b6ec387a 100644 --- a/PDO/DataObject/Introspection.php +++ b/PDO/DataObject/Introspection.php @@ -31,6 +31,7 @@ */ +#[AllowDynamicProperties] abstract class PDO_DataObject_Introspection { /** diff --git a/PDO/DataObject/Join.php b/PDO/DataObject/Join.php index 42db189b..159baa0d 100644 --- a/PDO/DataObject/Join.php +++ b/PDO/DataObject/Join.php @@ -75,6 +75,7 @@ * * */ +#[AllowDynamicProperties] class PDO_DataObject_Join { private $do; diff --git a/PDO/DataObject/Links.php b/PDO/DataObject/Links.php index 7ec71907..be13c4f5 100644 --- a/PDO/DataObject/Links.php +++ b/PDO/DataObject/Links.php @@ -42,7 +42,8 @@ * * @package DB_DataObject */ -class PDO_DataObject_Links +#[AllowDynamicProperties] +class PDO_DataObject_Links { /** * @property {DB_DataObject} do DataObject to apply this to. diff --git a/PDO/DataObject/Validate.php b/PDO/DataObject/Validate.php index a534bd34..a203cc5a 100644 --- a/PDO/DataObject/Validate.php +++ b/PDO/DataObject/Validate.php @@ -32,6 +32,7 @@ +#[AllowDynamicProperties] class PDO_DataObject_Validate { diff --git a/tests/37-buffered.phpt b/tests/37-buffered.phpt index eeda8e50..e264ac3e 100644 --- a/tests/37-buffered.phpt +++ b/tests/37-buffered.phpt @@ -35,7 +35,11 @@ echo "\n\n--------\n"; echo "basic load a big result set\n" ; -PDO_DataObject::factory('Events')->PDO()->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); +$mysqlAttrUseBufferedQuery = defined('Pdo\\Mysql::ATTR_USE_BUFFERED_QUERY') + ? constant('Pdo\\Mysql::ATTR_USE_BUFFERED_QUERY') + : PDO::MYSQL_ATTR_USE_BUFFERED_QUERY; + +PDO_DataObject::factory('Events')->PDO()->setAttribute($mysqlAttrUseBufferedQuery, false); $x = PDO_DataObject::factory('Events'); $x->find(); diff --git a/tests/includes/PDO_Dummy.php b/tests/includes/PDO_Dummy.php index 5bb144d1..4ff25051 100644 --- a/tests/includes/PDO_Dummy.php +++ b/tests/includes/PDO_Dummy.php @@ -33,14 +33,20 @@ function __construct($dsn,$user,$pass, $options) function getAttribute($key) { + // PDO::MYSQL_ATTR_USE_BUFFERED_QUERY is deprecated since PHP 8.5 in favor of + // Pdo\Mysql::ATTR_USE_BUFFERED_QUERY (only available from PHP 8.4 onwards). + $mysqlAttrUseBufferedQuery = defined('Pdo\\Mysql::ATTR_USE_BUFFERED_QUERY') + ? constant('Pdo\\Mysql::ATTR_USE_BUFFERED_QUERY') + : PDO::MYSQL_ATTR_USE_BUFFERED_QUERY; + switch($key) { case PDO::ATTR_DRIVER_NAME: // it does this alot!!!? //echo __FUNCTION__ . '==' . json_encode(func_get_args()) . " => " . $this->_dbtype . "\n"; return $this->_dbtype; break; - - case PDO::MYSQL_ATTR_USE_BUFFERED_QUERY: + + case $mysqlAttrUseBufferedQuery: return 1; default: