Hello Internals of PHP,
I’d like to get feedback on a potential language feature before considering
whether it deserves an RFC.
Currently, PHP does not provide a general way to distinguish between:
- a variable or property that has never been assigned, and
- one that was explicitly assigned the value null.
isset() treats both cases identically, property_exists() only reflects
declarations, and ReflectionProperty::isInitialized() works only for typed
properties and does not help differentiate explicit null from absence in
the broader sense.
There are workarounds involving reflection and string-based
variable/property names, but these approaches rely on dynamic access, which
is not ideal for developer experience, particularly regarding static
analysis, IDE autocompletion, and refactoring safety.
I’m interested in hearing whether there is openness to exploring a built-in
mechanism that can reliably distinguish these states at the language level.
At this point I’m only seeking initial feedback to understand whether this
aligns with PHP’s direction, and whether it would be worth developing into
a formal RFC.
related issue: https://github.com/php/php-src/issues/20663
Thank you for your time.
-- Hichem Taboukouyout.
Hichem Taboukouyout
Full-stack Developer & Engineer in Industrial and Tertiary Systems (GSIT)
✉️ hichem.taboukouyout@hichemtab-tech.me
--
──────────────────────────
Hichem Taboukouyout
Full-stack Developer &
Engineer in Industrial and Tertiary Systems (GSIT)
📧
hichem.taboukouyout@hichemtab-tech.me
mailto:hichem.taboukouyout@hichemtab-tech.me
🌐 hichemtab-tech.me
http://hichemtab-tech.me
LinkedIn:
https://dz.linkedin.com/in/hichem-taboukouyout
https://dz.linkedin.com/in/hichem-taboukouyout
GitHub:
github.com/HichemTab-tech <http://github.com/HichemTab-tech
Hello Internals of PHP,
I’d like to get feedback on a potential language feature before
considering whether it deserves an RFC.Currently, PHP does not provide a general way to distinguish between:
- a variable or property that has never been assigned, and
- one that was explicitly assigned the value null.
Hi Hichem,
This is something which has been discussed several times over the years,
and consensus has generally been against.
My own view is largely unchanged since I wrote these two Stack Overflow
answers a decade ago: https://stackoverflow.com/a/18646568/157957 and
https://stackoverflow.com/a/18601583/157957
In short: any algorithm which needs to distinguish between "never
assigned" and "currently contains null" can and should be rewritten to
instead use some other distinction - a separate boolean tracking the
state, or additional values which can be distinguished directly.
Key-value maps built with associative arrays or dynamic objects are an
exception to this rule, but we already have array_key_exists and
property_exists for those use cases.
One thing that has changed is that we now have native, opaque, enums; so
many cases assigning specific meaning to null can be rewritten to be
more expressive.
For example, instead of this:
/** @var ?string $inputFile */
if ( $inputFile === null ) {
// do something with standard input
}
else {
// verify and use the given input file in some way
}
You can write this:
enum InputFileOption { case STDIN; }
/** @var string|InputFileOption $inputFile */
if ( $inputFile === InputFileOption::STDIN ) {
// do something with standard input
}
else {
// verify and use the given input file in some way
}
Then instead of wanting a new "very null" check:
/** @var ??string $inputFile */
if ( ! is_assigned($inputFile) ) {
// complain that the user didn't provide an answer
}
else if ( $inputFile === null ) {
// do something with standard input
}
else {
// verify and use the given input file in some way
}
You can just add a case to the enum:
enum InputFileOption { case STDIN; case NOT_CONFIGURED; }
/** @var string|InputFileOption $inputFile */
if ( $inputFile === InputFileOption::NOT_CONFIGURED ) {
// complain that the user didn't provide an answer
}
else if ( $inputFile === InputFileOption::STDIN ) {
// do something with standard input
}
else {
// verify and use the given input file in some way
}
And unlike using "null" and "unassigned" for your special states, you
can carry on adding more cases whenever you want.
Regards,
--
Rowan Tommins
[IMSoP]