[PHP-DEV] [RFC] [Discussion] array_get and array_has functions

On Mon, Apr 6, 2026, at 10:01 AM, Barel wrote:

Following some comments from some users I have decided to also allow
the $key parameter to be a list of strings/ints so that this
functionality can also be used without using dot notation. I believe
this also removes the need to add any kind of dot escaping. If your
segments can contain dots, just use the form of the function that
accepts an array.

It was suggested that accepting an iterable would be a good addition
but none of the array_ functions accept an iterable so I don't think it
would be good to make an exception here

The proposed implementation in GitHub has also been updated with this change

Cheers

Carlos

Please remember to bottom post. :slight_smile:

It looks like the RFC hasn't been fully updated for array-based "keys" yet. The function signatures in most of the examples still say string|int|null.

Despite my long-standing and public crusade against arrays being used where an object belongs, I'm overall in favor of this direction. However, I would go all-in on the array syntax, not the dotted syntax. There's a few reasons for that.

1. The various notes around escaping. Having a string instruction format that doesn't handle escaping and encoding and other edge cases is asking for trouble, and it's trouble that will be harder to fix in the future. String instructions are always more complicated and nuanced than you expect, so a simple "split on the dot and now it's an array!" approach is just too rudimentary to be trustworthy, for all the reasons mentioned in previous posts.

2. If you're not building the path dynamically, then there is little advantage of it over what we have now.

array_get($array, 'foo.bar.1.baz', null);

$array['foo']['bar'][1]['baz'] ?? null

The second may be slightly slower to type because of the punctuation, but it's perfectly viable today.

Where it becomes interesting is when the path is variable... and if the path is variable, I'll probably want to be building it dynamically rather than just selecting one of a few hard-coded options. And if I'm building it dynamically, then string concatenation is an awful way to do that, for all the escaping reasons mentioned previously. We're back to concatenating SQL strings together, with all the risk that entails.

So I would be in favor of going all the way to

function array_get(array $array, array $path, mixed $default = null) {}

Or, for that matter, that is nearly the same as:

function array_get(array $array, array $path) {}

array_get($arr, $path) ?? null;

Which would allow using a variadic for the $path if desired, instead of an array. I'm not certain that's optimal, but I think it's worth discussing. array_has() would then follow suit.

Then, separately, I would be in favor of a full-on JSON Pointer implementation that can work on both arrays and JSON blobs, potentially (as the two are effectively isomorphic). Skip a custom dot notation. Go straight to the fully robust standard. Do not pass go, do not collect 200 security reports.

--Larry Garfield

On Mon, 6 Apr 2026 at 18:12, Larry Garfield <larry@garfieldtech.com> wrote:

On Mon, Apr 6, 2026, at 10:01 AM, Barel wrote:

Following some comments from some users I have decided to also allow
the $key parameter to be a list of strings/ints so that this
functionality can also be used without using dot notation. I believe
this also removes the need to add any kind of dot escaping. If your
segments can contain dots, just use the form of the function that
accepts an array.

It was suggested that accepting an iterable would be a good addition
but none of the array_ functions accept an iterable so I don’t think it
would be good to make an exception here

The proposed implementation in GitHub has also been updated with this change

Cheers

Carlos

Please remember to bottom post. :slight_smile:

It looks like the RFC hasn’t been fully updated for array-based “keys” yet. The function signatures in most of the examples still say string|int|null.

Despite my long-standing and public crusade against arrays being used where an object belongs, I’m overall in favor of this direction. However, I would go all-in on the array syntax, not the dotted syntax. There’s a few reasons for that.

  1. The various notes around escaping. Having a string instruction format that doesn’t handle escaping and encoding and other edge cases is asking for trouble, and it’s trouble that will be harder to fix in the future. String instructions are always more complicated and nuanced than you expect, so a simple “split on the dot and now it’s an array!” approach is just too rudimentary to be trustworthy, for all the reasons mentioned in previous posts.

  2. If you’re not building the path dynamically, then there is little advantage of it over what we have now.

array_get($array, ‘foo.bar.1.baz’, null);

$array[‘foo’][‘bar’][1][‘baz’] ?? null

The second may be slightly slower to type because of the punctuation, but it’s perfectly viable today.

Where it becomes interesting is when the path is variable… and if the path is variable, I’ll probably want to be building it dynamically rather than just selecting one of a few hard-coded options. And if I’m building it dynamically, then string concatenation is an awful way to do that, for all the escaping reasons mentioned previously. We’re back to concatenating SQL strings together, with all the risk that entails.

So I would be in favor of going all the way to

function array_get(array $array, array $path, mixed $default = null) {}

Or, for that matter, that is nearly the same as:

function array_get(array $array, array $path) {}

array_get($arr, $path) ?? null;

Which would allow using a variadic for the $path if desired, instead of an array. I’m not certain that’s optimal, but I think it’s worth discussing. array_has() would then follow suit.

Then, separately, I would be in favor of a full-on JSON Pointer implementation that can work on both arrays and JSON blobs, potentially (as the two are effectively isomorphic). Skip a custom dot notation. Go straight to the fully robust standard. Do not pass go, do not collect 200 security reports.

–Larry Garfield

Larry,

Thanks for pointing out that I had not updated the example code to include array in the type, this has now been updated

You raise some interesting points in your message. I would like to hear what other people think about them

Cheers

Carlos

On Monday 06 April 2026 18:21:20 (+02:00), Barel wrote:

> Larry,
> [...]
> You raise some interesting points in your message. I would like to hear
> what other people think about them

For leaving the default value out so that the splat (or was it spread?) operator can be used also in favour.

About JSON Pointer I already wrote, IMHO it should be referenced in the RFC prominently, e.g. above the Laravel or other existing implementation references as it is an actual standard.

-- hakre

On Mon, 6 Apr 2026 at 18:05, Michał Marcin Brzuchalski <michal.brzuchalski@gmail.com> wrote:

Hi Carlos,

The proposal looks simple on the surface, but it implicitly introduces a non-trivial policy for interpreting array keys, which is problematic at the language level.

In PHP, array keys are intentionally loose — any string is a valid key, including ones containing dots or other separators. Introducing “array_get()” / “array_has()” with dot-notation means that a plain string key like “‘user.name’” is no longer unambiguously a key; it may be interpreted as a path. That creates a semantic conflict with existing, perfectly valid data structures.

This is not just a syntactic concern — it’s a shift in the data model. The function starts encoding assumptions about how keys should be interpreted, rather than operating on arrays as they are defined by the language.

We can already see that this space is not universally agreed upon:

  • Laravel and Symfony both provide similar helpers, but they use different path semantics.
  • Questions like escaping, null handling, distinguishing “missing key” vs “null value”, or supporting ArrayAccess / objects are all policy decisions, not language primitives.

Because of that, these helpers are inherently convention-driven, not semantically neutral. Different ecosystems solve them differently, which is a strong signal that this abstraction belongs in userland, where such conventions can be chosen explicitly and consistently.

Putting this into core would effectively standardize one arbitrary interpretation of array paths, while PHP arrays themselves do not have such a concept.

Additionally, allowing “$key” to accept an “array” further weakens the conceptual model. A variable named “$key” strongly implies a single scalar identifier, while an array represents a sequence of path segments — effectively a different abstraction (“path”, “segments”, etc.). Mixing these under a single parameter name blurs the intent and makes the API harder to reason about.

In short:
“array_get()” with path notation does not operate on PHP arrays as defined — it operates on a particular convention for interpreting keys. That makes it better suited for userland libraries than for the core language.

Kind regards,

Michał Marcin Brzuchalski

sob., 4 kwi 2026, 16:07 użytkownik Barel <barel.barelon@gmail.com> napisał:

Hi,

I would like to open the discussion on my proposal to add two small, focused array functions for retrieving and checking nested array elements using dot notation.

This is the link to the RFC: https://wiki.php.net/rfc/array_get_and_array_has

This is the link to the proposed implementation: https://github.com/php/php-src/pull/21637

Thanks!!

Carlos

After the discussion here and after speaking to other developers, I have decided to drop the dot notation entirely from this RFC and only leave the option to use an array path. Using dot (or similar) notations can be easily achieved using a simple explode or more complex code if we need to do more complex setups like escaping. The main goal of the RFC has always been being able to handle dynamic paths. The implementation has also been updated and is now much simpler

Cheers

Carlos

Hi

Am 2026-04-04 16:06, schrieb Barel:

This is the link to the RFC:
PHP: rfc:array_get_and_array_has

Thank you for your RFC.

I find it not obvious at all that:

- Non-(string|int) path segments will result in the default value being returned, rather than a TypeError being thrown or just proceeding with implicit coercion.
- Encountering a non-array value along the path will result in the default value being returned, rather than an Exception being thrown. Returning a default value for an existing path element that is not an array feels like a source of error, particularly when any intermediate value is an object implementing ArrayAccess.

I would expect the following to hold:

     $path = ['foo', 'bar', 'baz'];
     array_get($array, $path) === array_get(array_get($array, array_shift($path), []), $path);

which it will not due to (2).

And the further looking at the examples:

     $array = /* … */;

     array_has($array, ['product', 'name']);
     array_has($array, ['product', 'color']);

Just looking at the code without knowing what the function does, I probably would have expected it to be either:

1. `in_array()` operating on multiple values that all need to be there.
2. `array_key_exists()` operating on multiple keys that all need to be there.

But not a “path through the array”.

Best regards
Tim Düsterhus

On Sat, Apr 11, 2026, at 5:30 AM, Barel wrote:

After the discussion here and after speaking to other developers, I
have decided to drop the dot notation entirely from this RFC and only
leave the option to use an array path. Using dot (or similar) notations
can be easily achieved using a simple explode or more complex code if
we need to do more complex setups like escaping. The main goal of the
RFC has always been being able to handle dynamic paths. The
implementation has also been updated and is now much simpler

Cheers

Carlos

"4) Using dot or similar notations "

This should be bullet point 3, not no 4.

I agree with Tim that an invalid path segment should error in some way, rather than just using the default. If a non-int/string path segment is encountered, it 100% of the time means the developer screwed up in some way so they should know to fix it.

One of the most common uses for structure-unclear arrays I run into is (bad) APIs that have a value that is either a primitive or an array of primitives. Can you include an example showing how these functions would help in that situation?

Eg, this JSON:

{ "state": "IL" }
vs
{"state": ["IL", "CA", "NY"] }

Presumably you also have some real-world cases in mind that you've run into. Can you include versions of those in the examples to get a better sense of what usage would look like in practice?

To Tim's naming point, perhaps `array_has_path()` / `array_get_path()`? (Or maybe `path` first, not sure.)

--Larry Garfield

On Mon, Apr 13, 2026, at 17:20, Larry Garfield wrote:

On Sat, Apr 11, 2026, at 5:30 AM, Barel wrote:

To Tim’s naming point, perhaps array_has_path() / array_get_path()? (Or maybe path first, not sure.)

–Larry Garfield

Can we please have array_path_has() and array_path_get()? Brings a whole new world to yoda-conditionals. /s

— Rob

On Mon, 13 Apr 2026 at 17:23, Larry Garfield <larry@garfieldtech.com> wrote:

On Sat, Apr 11, 2026, at 5:30 AM, Barel wrote:

After the discussion here and after speaking to other developers, I
have decided to drop the dot notation entirely from this RFC and only
leave the option to use an array path. Using dot (or similar) notations
can be easily achieved using a simple explode or more complex code if
we need to do more complex setups like escaping. The main goal of the
RFC has always been being able to handle dynamic paths. The
implementation has also been updated and is now much simpler

Cheers

Carlos

"4) Using dot or similar notations "

This should be bullet point 3, not no 4.

I agree with Tim that an invalid path segment should error in some way, rather than just using the default. If a non-int/string path segment is encountered, it 100% of the time means the developer screwed up in some way so they should know to fix it.

One of the most common uses for structure-unclear arrays I run into is (bad) APIs that have a value that is either a primitive or an array of primitives. Can you include an example showing how these functions would help in that situation?

Eg, this JSON:

{ “state”: “IL” }
vs
{“state”: [“IL”, “CA”, “NY”] }

Presumably you also have some real-world cases in mind that you’ve run into. Can you include versions of those in the examples to get a better sense of what usage would look like in practice?

To Tim’s naming point, perhaps array_has_path() / array_get_path()? (Or maybe path first, not sure.)

–Larry Garfield

Tim, Larry

Many thanks for your thoughtful comments.

  • I updated the bullet point number
  • I agree that if an invalid path segment is found it is better to throw a TypeError, this has been updated
  • I see the point that Tim made about the function names, I have updated them to array_get_path() and array_has_path()
  • Regarding the issue of returning the default if an intermediate segment is not an array, the philosophy of the function is: if the path exists, return the value, otherwise return the default. This cover uses cases like this: in yaml configuration many times you set a config option to ~ (null) and this many times indicates “use the default config”. So you may have something like:

database:
config: ~

Indicating that you want to use the default database config. If you convert this yaml file to an array an use the array_get_path function to get a value, for example array_get_path($config, [‘database’, ‘config’, ‘port’], 7766), you want to get 7766, not an exception or error. Tim points out that intermediate segments might be objects which implement ArrayAccess, but allowing this would complicate the code of the function a lot without much practical gain.

BTW, the URL to the RFC has changed and is now https://wiki.php.net/rfc/array_get_path_and_array_has_path

Cheers

Carlos

Hi

Am 2026-04-14 19:06, schrieb Barel:

BTW, the URL to the RFC has changed and is now
PHP: rfc:array_get_path_and_array_has_path

Please don't create new RFC documents for the same RFC. This breaks the version history and is super confusing, because the link in the discussion thread will go to an abandoned version of the RFC. In fact you forgot to adjust the link in the RFC overview at: PHP: rfc

Having an outdated name of the feature in the URL is fine - and typos are as well. The latter happened with my #[\Override] RFC, where I accidentally dropped the 'd' in 'overridden': PHP: rfc:marking_overriden_methods. Note how I also “described” the proposed feature in the RFC and the title - this was to make it independent of any naming bikeshedding that might happen :slight_smile:

Best regards
Tim Düsterhus

Hi

Am 2026-04-14 19:06, schrieb Barel:

- I see the point that Tim made about the function names, I have updated
them to array_get_path() and array_has_path()

Similarly to Rob's tongue in cheek comment, I think I would also prefer having a common prefix for the functions, since this improves discoverability. While there are some inconsistencies in the array API due to its age, I think there is a reasonably similar precedent with the `array_key_*()` functions. In fact looking at those, I wonder if the following pair of names would make sense for your proposed feature:

- array_path()
- array_path_exists()

From what I see, the functions in the array API don't mention “get” as the default operation, e.g. it's `array_first()`, not `array_get_first()`. And for “existence checks” there's the obvious precedent with `array_key_exists()` which is also used in the example implementation in your RFC.

- Regarding the issue of returning the default if an intermediate segment
is not an array, the philosophy of the function is: if the path exists,
return the value, otherwise return the default. This cover uses cases like
this: in yaml configuration many times you set a config option to ~ (null)
and this many times indicates "use the default config". So you may have
something like:

database:
    config: ~

Indicating that you want to use the default database config. If you convert
this yaml file to an array an use the array_get_path function to get a
value, for example array_get_path($config, ['database', 'config', 'port'],
7766), you want to get 7766, not an exception or error. Tim points out that
intermediate segments might be objects which implement ArrayAccess, but
allowing this would complicate the code of the function a lot without much
practical gain.

Perhaps the right solution is using “isset”-like semantics instead: `null` is treated as an absent entry (it can be debated if an explicit `null` at the end of the path should be treated as `null` rather than the default), array allows the traversal to continue and everything else results in a clear error. This would then allow to extend support to anything ArrayAccess in the future without a compatibility break. Generally “throwing an error” is always a safe option.

But saying that `array_get_path(['foo' => '???'], ['foo', 'bar'], 'default');` should result in `'default'` doesn't make sense to me and - staying with the config example - might mask configuration errors:

As an example, a user might accidentally configure a "DSN":

     database:
         connection: "mysql://root@db.example.com"

when in reality the library expects separate components:

     database:
         connection:
             driver: mysql
             host: db.example.com
             user: root

Now extracting the host with `array_get_path($config, ['database', 'connection', 'host'], 'localhost')` would erroneously fall back to default values instead of reporting a clear error.

Best regards
Tim Düsterhus

On Wed, 15 Apr 2026 at 19:58, Tim Düsterhus <tim@bastelstu.be> wrote:

Hi

Am 2026-04-14 19:06, schrieb Barel:

BTW, the URL to the RFC has changed and is now
https://wiki.php.net/rfc/array_get_path_and_array_has_path

Please don’t create new RFC documents for the same RFC. This breaks the
version history and is super confusing, because the link in the
discussion thread will go to an abandoned version of the RFC. In fact
you forgot to adjust the link in the RFC overview at:
https://wiki.php.net/rfc

Having an outdated name of the feature in the URL is fine - and typos
are as well. The latter happened with my #[\Override] RFC, where I
accidentally dropped the ‘d’ in ‘overridden’:
https://wiki.php.net/rfc/marking_overriden_methods. Note how I also
“described” the proposed feature in the RFC and the title - this was to
make it independent of any naming bikeshedding that might happen :slight_smile:

Best regards
Tim Düsterhus

Thanks, I have recovered the previous RFC and updated it with the latest changes

https://wiki.php.net/rfc/array_get_and_array_has

Cheers

Carlos

On Wed, 15 Apr 2026 at 20:18, Tim Düsterhus <tim@bastelstu.be> wrote:

Hi

Am 2026-04-14 19:06, schrieb Barel:

  • I see the point that Tim made about the function names, I have
    updated
    them to array_get_path() and array_has_path()

Similarly to Rob’s tongue in cheek comment, I think I would also prefer
having a common prefix for the functions, since this improves
discoverability. While there are some inconsistencies in the array API
due to its age, I think there is a reasonably similar precedent with the
array_key_*() functions. In fact looking at those, I wonder if the
following pair of names would make sense for your proposed feature:

  • array_path()
  • array_path_exists()

From what I see, the functions in the array API don’t mention “get” as
the default operation, e.g. it’s array_first(), not
array_get_first(). And for “existence checks” there’s the obvious
precedent with array_key_exists() which is also used in the example
implementation in your RFC.

Tim, thanks again for your comments. I did not like using array_path._... because the function name reads less naturally, but I agree that it improves discoverability and is more in line with existing functions like array_key_exists. Also agree that using exists instead of has is better. So I updated the function names to array_path_get and array_path_exists. I have preferred to keep get in the function name because I think that array_path is less clear about what the function does. RFC and implementation have been updated.

  • Regarding the issue of returning the default if an intermediate
    segment
    is not an array, the philosophy of the function is: if the path exists,
    return the value, otherwise return the default. This cover uses cases
    like
    this: in yaml configuration many times you set a config option to ~
    (null)
    and this many times indicates “use the default config”. So you may have
    something like:

database:
config: ~

Indicating that you want to use the default database config. If you
convert
this yaml file to an array an use the array_get_path function to get a
value, for example array_get_path($config, [‘database’, ‘config’,
‘port’],
7766), you want to get 7766, not an exception or error. Tim points out
that
intermediate segments might be objects which implement ArrayAccess, but
allowing this would complicate the code of the function a lot without
much
practical gain.

Perhaps the right solution is using “isset”-like semantics instead:
null is treated as an absent entry (it can be debated if an explicit
null at the end of the path should be treated as null rather than
the default), array allows the traversal to continue and everything else
results in a clear error. This would then allow to extend support to
anything ArrayAccess in the future without a compatibility break.
Generally “throwing an error” is always a safe option.

But saying that array_get_path(['foo' => '???'], ['foo', 'bar'], 'default'); should result in 'default' doesn’t make sense to me and -
staying with the config example - might mask configuration errors:

As an example, a user might accidentally configure a “DSN”:

database:
connection: “mysql://root@db.example.com

when in reality the library expects separate components:

database:
connection:
driver: mysql
host: db.example.com
user: root

Now extracting the host with array_get_path($config, ['database', 'connection', 'host'], 'localhost') would erroneously fall back to
default values instead of reporting a clear error.

I am still unconvinced about this. Your proposal seems to give the null a special value and I think that in general the full semantics are less clear. And I don’t really like the function throwing errors for paths, I think that this function is great for defensive access to values, where you can be sure that you don’t need to be checking the path all the time. The existing implementations in Laravel and Lodash do not throw any error if an intermediate value is not an array (or object for Lodash) and instead return the default, so I think it is best to keep this behaviour

Cheers

Carlos

Hi

Am 2026-04-18 08:06, schrieb Barel:

`array_path_exists`. I have preferred to keep `get` in the function name
because I think that `array_path` is less clear about what the function
does. RFC and implementation have been updated.

No strong preference regarding the `_get()` suffix from my side.

I am still unconvinced about this. Your proposal seems to give the `null`
a special value and I think that in general the full semantics are less

null being a value indicating absence is by no means “special” in my suggestion. As previously mentioned, it's the semantics of `isset()`. It's also what `array_find()` and `array_find_key()` return. It has special syntax in types with the questionmark in `?Type`. It's what you get when you read a non-existent value.

clear. And I don't really like the function throwing errors for paths, I
think that this function is great for defensive access to values, where you
can be sure that you don't need to be checking the path all the time. The

Defensive access to me also implies throwing errors *where appropriate*, namely trying to perform an operation that is not meaningful. Trying to access an array offset on a string is not meaningful and trying to do *something* is not likely what the user intended to do. Similarly users passing in `ArrayAccess` objects might reasonably expect them to “just work”. Returning a default value instead of a clear error will likely lead to them thinking they found a bug in PHP.

existing implementations in Laravel and Lodash do not throw any error if an
intermediate value is not an array (or object for Lodash) and instead
return the default, so I think it is best to keep this behaviour

I don't think that lodash is quite comparable here, because JavaScript is quite different to PHP in that *everything* is an object. Thus `_.get({"foo": "bar"}, "foo.length.toString")` is meaningful (namely it returns `Number.prototype.toString()`).

As for the Laravel comparison, from what I see, they *do* support any `ArrayAccess`, so the function is also not comparable.

I've also taken another look at the RFC and have the following additional comments:

- The “Invalid array path segments” example is outdated, `stdClass` in the path should throw.
- The types of the path-segments should be pre-validated for consistent error reporting. Meaning:

     array_path_get($array, ['foo', 'bar', new stdClass()])

should consistently throw, independent of whether `$array` is `[]`, `["foo" => []]`, `["foo" => ["bar" => []]` or something else.

- I also wonder if `$path` should just be `string[]` instead of `(int|string)[]`. In the context of array keys, `"123"` is equivalent to `123` anyways.

Best regards
Tim Düsterhus

On Sun, Apr 19, 2026, at 10:06 AM, Tim Düsterhus wrote:

Hi

Am 2026-04-18 08:06, schrieb Barel:

I am still unconvinced about this. Your proposal seems to give the
`null`
a special value and I think that in general the full semantics are less

null being a value indicating absence is by no means “special” in my
suggestion. As previously mentioned, it's the semantics of `isset()`.
It's also what `array_find()` and `array_find_key()` return. It has
special syntax in types with the questionmark in `?Type`. It's what you
get when you read a non-existent value.

clear. And I don't really like the function throwing errors for paths,
I
think that this function is great for defensive access to values, where
you
can be sure that you don't need to be checking the path all the time.
The

Defensive access to me also implies throwing errors *where appropriate*,
namely trying to perform an operation that is not meaningful. Trying to
access an array offset on a string is not meaningful and trying to do
*something* is not likely what the user intended to do. Similarly users
passing in `ArrayAccess` objects might reasonably expect them to “just
work”. Returning a default value instead of a clear error will likely
lead to them thinking they found a bug in PHP.

Just to make sure we're talking about the same thing here. Tim, you're suggesting that this:

$a = ['foo' => 'bar'];
$val = array_path_get($a, ['foo', 'bar', 'baz']);

Should error rather than returning null?

If so, then I do not agree. The purpose of these functions, as I see it, is for dealing with inconsistently structured, wonky, arguably stupidly-designed data. (Which is a lot of REST APIs in the wild, sadly.) If the array were clearly, consistently, and properly structured, we could reliably just do $a['foo']['bar'] and move on with life. Or trivially convert it to a properly typed object. These functions are for cases where those are not viable or convenient options, meaning cases where a given value could be a string or an array, because the data model author hates you. (As noted in a previous reply, I have run into such structures where the value of a JSON key is string|string{}. It bloody well sucks.)

So in that sort of case, I'm not sure it's useful to distinguish between "There is no baz key on the array at foo.bar" and "foo.bar is a string, not an array, wat?" If that was a distinction that mattered, I'd be using ?? or converting to an object or whatever else already.

--Larry Garfield

Hi

Am 2026-04-20 17:18, schrieb Larry Garfield:

Just to make sure we're talking about the same thing here. Tim, you're suggesting that this:

$a = ['foo' => 'bar'];
$val = array_path_get($a, ['foo', 'bar', 'baz']);

Should error rather than returning null?

Yes.

If the array were clearly, consistently, and properly structured, we could reliably just do $a['foo']['bar'] and move on with life.
[…]
So in that sort of case, I'm not sure it's useful to distinguish between "There is no baz key on the array at foo.bar" and "foo.bar is a string, not an array, wat?" […]

The goal of the RFC is replacing `$a['foo']['bar']` where the *path is dynamic*. Quoting right from the introduction of the RFC:

When the structure of the array is known in advance and the exact element to retrieve is hardcoded, existing PHP syntax works well […]

And quoting further from the introduction:

array_path_get() retrieves a value from a deeply nested array and returns a default value if the path does not exist.

I'm arguing that a “(value at) path does not exist” is something fundamentally different from “value encountered on path cannot be traversed further”.

converting to an object

I agree that the correct solution in the general case is “use a proper object mapper” (such as Valinor) and don't see much personal value in having the proposed functions. But if they exist, I would want them to behave as safely as possible and that includes erroring if they cannot make sense of the data. Emitting a Warning when encountering an improperly typed value across the path would also work for me, but I suppose that others won't be in favor of *that* :slight_smile:

Best regards
Tim Düsterhus

Tim,

Many thanks for your comments regarding the RFC, I have updated it. Regarding the issue of throwing errors if a path cannot be traversed due to an intermediate step not being an array, I tend to agree with Larry so I am leaving this as it is for the time being

Cheers

Carlos

On Mon, 20 Apr 2026 at 19:07, Tim Düsterhus <tim@bastelstu.be> wrote:

Hi

Am 2026-04-20 17:18, schrieb Larry Garfield:

Just to make sure we’re talking about the same thing here. Tim, you’re
suggesting that this:

$a = [‘foo’ => ‘bar’];
$val = array_path_get($a, [‘foo’, ‘bar’, ‘baz’]);

Should error rather than returning null?

Yes.

If the array were clearly, consistently, and properly structured, we
could reliably just do $a[‘foo’][‘bar’] and move on with life.
[…]
So in that sort of case, I’m not sure it’s useful to distinguish
between “There is no baz key on the array at foo.bar” and “foo.bar is a
string, not an array, wat?” […]

The goal of the RFC is replacing $a['foo']['bar'] where the path is
dynamic
. Quoting right from the introduction of the RFC:

When the structure of the array is known in advance and the exact
element to retrieve is hardcoded, existing PHP syntax works well […]

And quoting further from the introduction:

array_path_get() retrieves a value from a deeply nested array and
returns a default value if the path does not exist.

I’m arguing that a “(value at) path does not exist” is something
fundamentally different from “value encountered on path cannot be
traversed further”.

converting to an object

I agree that the correct solution in the general case is “use a proper
object mapper” (such as Valinor) and don’t see much personal value in
having the proposed functions. But if they exist, I would want them to
behave as safely as possible and that includes erroring if they cannot
make sense of the data. Emitting a Warning when encountering an
improperly typed value across the path would also work for me, but I
suppose that others won’t be in favor of that :slight_smile:

Best regards
Tim Düsterhus

Hi

Am 2026-04-25 21:37, schrieb Barel:

Many thanks for your comments regarding the RFC, I have updated it.

I'm seeing you adjusted the text to mention “If any segment is not a string or integer: throw a TypeError, even if that segment would not be reached”. This is however not reflected in the example implementation.

Best regards
Tim Düsterhus

PS: Don't forget to cut your quotes when replying :slight_smile:

On Thu, 30 Apr 2026 at 09:34, Tim Düsterhus <tim@bastelstu.be> wrote:

Hi

Am 2026-04-25 21:37, schrieb Barel:

Many thanks for your comments regarding the RFC, I have updated it.

I’m seeing you adjusted the text to mention “If any segment is not a
string or integer: throw a TypeError, even if that segment would not be
reached”. This is however not reflected in the example implementation.

Thanks for pointing this out. This has been updated in the RFC

Carlos

Hi,

It’s been more than 14 days since the last major change to this RFC so I plan to start the voting phase next Monday

Cheers

Carlos

On Sat, 2 May 2026 at 09:28, Barel <barel.barelon@gmail.com> wrote:

On Thu, 30 Apr 2026 at 09:34, Tim Düsterhus <tim@bastelstu.be> wrote:

Hi

Am 2026-04-25 21:37, schrieb Barel:

Many thanks for your comments regarding the RFC, I have updated it.

I’m seeing you adjusted the text to mention “If any segment is not a
string or integer: throw a TypeError, even if that segment would not be
reached”. This is however not reflected in the example implementation.

Thanks for pointing this out. This has been updated in the RFC

Carlos