Uninitialized properties are really useful.
Being skipped in foreach loops and JSON encoded results and other
behaviours around uninitialized properties save a lot of time wasted on
basic checks and uncaught logical mistakes around null values.

With the introduction of named arguments and promoted constructor
properties and read-only classes, it would be great to have the true
ability to not specify a value.

class DTO {
    public function __construct(
        public string $id = uninitialized,
        public string $name = uninitialized,
        public null|int $age = uninitialized,
    ) {}
}

$dto = new DTO(id: 'someid', age: null);
if ($dto->age === null) echo "no age was given\n";
echo  $dto->name, PHP_EOL; // triggers the standard access before
initialisation error


EXAMPLE: A graphQL like API that only returns data that was asked for, is
serviced by a PHP class that only fetched the data that was asked for and
thus the DTO only has assigned values if they were fetched.
(These situations usually way more complex involving multiple SQL
joins/filters etc and nested objects/arrays in the return DTO).

The DTO object has all the possible values defined on the class for type
safety and IDE indexing, but allows the uninitialized error to happen if
you try to use data that was never requested.
Uninitialized Errors when directly accessing a property that was not
assigned is also desirable as it indicates a logical error instead of
thinking the value is null. Null is considered a real value in the database
in countless situations and API can assign null to delete a value from an
object.

Additionally, since array unpacking now directly maps to named
arguments this would also save a ton of mapping code.

*//array unpacking direct from the source
*$dto = new DTO( ...$sqlData);

(FYI: SQL is way faster at mapping thousands of values to the naming
convention of the class than doing it in php so we do it in SQL. So yes we
would directly array unpack an sql result here.)

I have is a discussion on this in github here:
https://github.com/php/php-src/issues/17771

The current workaround is to make the constructor take an array as its only
parameter and looping over it assigning matching array key values to class
properties and ignoring the rest.

This works but breaks indexing and prevents the use of class inheritance
because not all the properties can be seen from the same scope forcing
every extender of the class to copy paste the constructor code from the
parent class.


-- 

Bradley Hayes / Engineer / TITHE.LY <http://tithe.ly/>

<http://tithe.ly>

Reply via email to