[php-src] Issue #8688: PHP 8.1: key(), current(), next(), prev(), reset() and end() on \stdClass should not be deprecated

From: Date: Thu, 02 Jun 2022 11:49:42 +0000
Subject: [php-src] Issue #8688: PHP 8.1: key(), current(), next(), prev(), reset() and end() on \stdClass should not be deprecated
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-241650@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/8688 Author: MircoBabin ### Description The following code: ```php <?php // Laravel 9 / Eloquent: DB::getSchemaBuilder()->getAllTables() // Executes MySql query: SHOW FULL TABLES WHERE table_type = 'BASE TABLE' // Returns an array of \stdClass objects using PDO. // // The problem is that the name of the first column is databasename dependent 'Tables_in_'+databasename. // e.g. If the databasename is 'tripportal' the first columnname will be 'Tables_in_tripportal'. // Retrieving the first column value is cumbersome, because it has not a fixed name. // https://wiki.php.net/rfc/deprecations_php_8_1 // * key(), current(), next(), prev(), and reset() on objects function startTest($name, $func) { echo PHP_EOL; echo '------------------------------------------------------------------------------'.PHP_EOL; echo '[BEGIN] '.$name.PHP_EOL; $func(); echo '[END] '.$name.PHP_EOL; } $row = new \stdClass(); $row->Tables_in_tripportal = 'users'; $row->Table_type = 'BASE TABLE'; startTest('foreach', function () use ($row) { foreach($row as $columnName => $value) { echo $columnName.' => '.$value.PHP_EOL; } }); startTest('key', function () use ($row) { $firstColumnName = key($row); echo $firstColumnName.PHP_EOL; }); startTest('current', function () use ($row) { $firstColumnValue = current($row); echo $firstColumnValue.PHP_EOL; }); startTest('reset', function () use ($row) { $firstColumnValue = reset($row); echo $firstColumnValue.PHP_EOL; }); startTest('next', function () use ($row) { $firstColumnValue = reset($row); $secondColumnValue = next($row); echo $secondColumnValue.PHP_EOL; }); startTest('end', function () use ($row) { $secondColumnValue = end($row); echo $secondColumnValue.PHP_EOL; }); startTest('prev', function () use ($row) { $secondColumnValue = end($row); $firstColumnValue = prev($row); echo $firstColumnValue.PHP_EOL; }); startTest('reset(array)', function () use ($row) { $firstColumnValue = reset((array)$row); echo $firstColumnValue.PHP_EOL; }); ``` Resulted in this output: ``` ------------------------------------------------------------------------------ [BEGIN] foreach Tables_in_tripportal => users Table_type => BASE TABLE [END] foreach ------------------------------------------------------------------------------ [BEGIN] key Deprecated: key(): Calling key() on an object is deprecated in D:\Projects\Webpage\tripportals\testStdClassAsArray.php on line 38 Tables_in_tripportal [END] key ------------------------------------------------------------------------------ [BEGIN] current Deprecated: current(): Calling current() on an object is deprecated in D:\Projects\Webpage\tripportals\testStdClassAsArray.php on line 43 users [END] current ------------------------------------------------------------------------------ [BEGIN] reset Deprecated: reset(): Calling reset() on an object is deprecated in D:\Projects\Webpage\tripportals\testStdClassAsArray.php on line 48 users [END] reset ------------------------------------------------------------------------------ [BEGIN] next Deprecated: reset(): Calling reset() on an object is deprecated in D:\Projects\Webpage\tripportals\testStdClassAsArray.php on line 53 Deprecated: next(): Calling next() on an object is deprecated in D:\Projects\Webpage\tripportals\testStdClassAsArray.php on line 54 BASE TABLE [END] next ------------------------------------------------------------------------------ [BEGIN] end Deprecated: end(): Calling end() on an object is deprecated in D:\Projects\Webpage\tripportals\testStdClassAsArray.php on line 59 BASE TABLE [END] end ------------------------------------------------------------------------------ [BEGIN] prev Deprecated: end(): Calling end() on an object is deprecated in D:\Projects\Webpage\tripportals\testStdClassAsArray.php on line 64 Deprecated: prev(): Calling prev() on an object is deprecated in D:\Projects\Webpage\tripportals\testStdClassAsArray.php on line 65 users [END] prev ------------------------------------------------------------------------------ [BEGIN] reset(array) Fatal error: Uncaught Error: reset(): Argument #1 ($array) cannot be passed by reference in D:\Projects\Webpage\tripportals\testStdClassAsArray.php:70 Stack trace: #0 D:\Projects\Webpage\tripportals\testStdClassAsArray.php(21): {closure}() #1 D:\Projects\Webpage\tripportals\testStdClassAsArray.php(72): startTest('reset(array)', Object(Closure)) #2 {main} thrown in D:\Projects\Webpage\tripportals\testStdClassAsArray.php on line 70 ``` But I expected this output instead: ``` No deprecation warnings about calling ... on an object is deprecated. ``` --- I can't understand why the [RFC deprecations 8.1](https://wiki.php.net/rfc/deprecations_php_8_1) has not taken *\stdClass* into account. I believe \stdClass should be an exception. Because \stdClass and array are positioned throughout the documentation as interchangable. It is easy to cast from array to \stdClass and vice versa. And Laravel 9 with Eloquent is using \stdClass when not using models for querying the MySql database. I had this code: ```php <?php $table_name = reset($row); ``` And now I have to change this to: ```php <?php $table_name = current((array) $row); // NOTE: the RFC presented below alternative. But this just gives a Fatal error. // $table_name = reset((array) $row); // Fatal error: Uncaught Error: reset(): Argument #1 ($array) cannot be passed by reference in D:\Projects\Webpage\tripportals\testStdClassAsArray.php:70 ``` I don't see this as an approvement of the language. Note, I'm only talking about \stdClass, not about other objects. The RFC states: > As such, the proposal is to deprecate key(), current(), next(), prev() and reset() on objects. > The suggested replacement is to cast the object to array first, or call get_mangled_object_vars(), > depending on what the intention is. But this is a false assumption, because ``reset((array) $row);` gives a `Fatal error: Uncaught Error: reset(): Argument #1 ($array) cannot be passed by reference``. ### PHP Version PHP 8.1.4 ### Operating System Windows/10

« previous php.bugs (#241650) next »