Skip to content

PHP 8.5.0 regression: PDO::FETCH_CLASSTYPE ignores $constructorArgs #20553

@fds242

Description

@fds242

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)

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions