-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Description
Description
The following code:
<?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 key(), current(), reset(), next(), end(), prev() on an object is deprecated.
I can't understand why the RFC deprecations 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
$table_name = reset($row);
And now I have to change this to:
<?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