-
Notifications
You must be signed in to change notification settings - Fork 8k
Open
Description
Description
In PHP 8.5.0, if the PDO::FETCH_CLASS fetch $mode is paired with PDO::FETCH_CLASSTYPE, the $constructorArgs parameter is ignored, and does not get passed to the class constructor as documented, or as has worked in every previous PHP release.
The following code:
<?php
class dumpy {
function __construct() {
echo 'constructor called,' . PHP_EOL . ' my class is ' .
var_export(get_class($this), true) . PHP_EOL .
' input parameters: ' .
var_export(func_get_args(), true) . PHP_EOL;
}
function __set($name, $value) {
echo var_export($name, true) . ' = ' . var_export($value, true) .
PHP_EOL;
}
}
class dummy extends dumpy {
}
$dsn = 'sqlite::memory:';
$pdo = method_exists('PDO', 'connect') ? PDO::connect($dsn) : new PDO($dsn);
$sql = "SELECT 'dummy' pdoFetchClassTypeClass, 'bar' foo, 'dfg' abc;";
foreach (array(
array('PDO::FETCH_CLASS'),
array('PDO::FETCH_CLASS', 'PDO::FETCH_PROPS_LATE'),
array('PDO::FETCH_CLASS', 'PDO::FETCH_CLASSTYPE'),
array('PDO::FETCH_CLASS', 'PDO::FETCH_CLASSTYPE', 'PDO::FETCH_PROPS_LATE'),
) as $fetchMode) {
$fetchModeInt = 0;
foreach (array_map('constant', $fetchMode) as $i) {
$fetchModeInt |= $i;
}
echo '## ' . implode(' | ' , $fetchMode) . " ($fetchModeInt)" . PHP_EOL;
$pdo->query($sql)->fetchAll(
$fetchModeInt,
'dumpy',
array('constructor argument #1')
);
echo PHP_EOL;
}Resulted in this output:
## PDO::FETCH_CLASS (8)
'pdoFetchClassTypeClass' = 'dummy'
'foo' = 'bar'
'abc' = 'dfg'
constructor called,
my class is 'dumpy'
input parameters: array (
0 => 'constructor argument #1',
)
## PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE (264)
constructor called,
my class is 'dumpy'
input parameters: array (
0 => 'constructor argument #1',
)
'pdoFetchClassTypeClass' = 'dummy'
'foo' = 'bar'
'abc' = 'dfg'
## PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE (136)
'foo' = 'bar'
'abc' = 'dfg'
constructor called,
my class is 'dummy'
input parameters: array (
)
## PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE | PDO::FETCH_PROPS_LATE (392)
constructor called,
my class is 'dummy'
input parameters: array (
)
'foo' = 'bar'
'abc' = 'dfg'
But I expected this output instead:
## PDO::FETCH_CLASS (8)
'pdoFetchClassTypeClass' = 'dummy'
'foo' = 'bar'
'abc' = 'dfg'
constructor called,
my class is 'dumpy'
input parameters: array (
0 => 'constructor argument #1',
)
## PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE (1048584)
constructor called,
my class is 'dumpy'
input parameters: array (
0 => 'constructor argument #1',
)
'pdoFetchClassTypeClass' = 'dummy'
'foo' = 'bar'
'abc' = 'dfg'
## PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE (262152)
'foo' = 'bar'
'abc' = 'dfg'
constructor called,
my class is 'dummy'
input parameters: array (
0 => 'constructor argument #1',
)
## PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE | PDO::FETCH_PROPS_LATE (1310728)
constructor called,
my class is 'dummy'
input parameters: array (
0 => 'constructor argument #1',
)
'foo' = 'bar'
'abc' = 'dfg'
Notice that if PDO::FETCH_CLASSTYPE is used, 0 => 'constructor argument #1', no longer gets passed on.
See test on 3v4l.org: PHP 8.5.0 bug: PDO::FETCH_CLASSTYPE ignores $constructorArgs
PHP Version
PHP 8.5.0 (cli) (built: Nov 21 2025 08:04:40) (NTS Clang 17.0.0 arm64)
Copyright (c) The PHP Group
Zend Engine v4.5.0, Copyright (c) Zend Technologies
with Zend OPcache v8.5.0, Copyright (c), by Zend Technologies
PHP 8.5.0 (cli) (built: Nov 21 2025 09:43:28) (NTS GCC 14.2.0 x86_64)
Copyright (c) The PHP Group
Zend Engine v4.5.0, Copyright (c) Zend Technologies
with Zend OPcache v8.5.0, Copyright (c), by Zend Technologies
PHP 8.5.0 (cli) (built: Nov 19 2025 09:56:40) (NTS Visual C++ 2022 x64)
Copyright (c) The PHP Group
Zend Engine v4.5.0, Copyright (c) Zend Technologies
with Zend OPcache v8.5.0, Copyright (c), by Zend Technologies
Operating System
not relevant (reproduced on macOS 26.1 Intel & ARM, Windows 11, and 3v4l.org)