Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130664 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id 91FA91A00BC for ; Sat, 18 Apr 2026 06:07:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1776492433; bh=acnYIvbzGvx/A1NSxkQHzHCzXvEyNvKo4AekcxpBwTA=; h=References:In-Reply-To:From:Date:Subject:To:From; b=FHiHgRkv/gwi8W0wo0AZkMXt8pU1g4IANSn/S52h+drjielVICHP0GOUFLNcNfKcz 8s39AGlYRYQk6tFfFzCDfNGtAwP+DfmZHaA/OiALwt8s4qGlDBoRPkzqjmgNV2/Y61 hjHc8PXAmF/WhJJXUnfYgMKN1du92iEuMZDbPaOVsUHpogf2ZAbQoFsTIYh9/MoM0+ TPtj2cJ7hk2sJ/3sfAk7PFcq2n8iv7gKuFJOEqeQN2C9oqGzPgsIfR7qeShzMu64Q1 o254hPkhddnJME+zyqBUsKE9uCt+uKvPSQY8b0R5ZtQ7VBM9oSPousfGQ6C7K4MbOZ zgjJ8px16qLnA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id B2C1D180078 for ; Sat, 18 Apr 2026 06:07:11 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: * X-Spam-Status: No, score=1.6 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_50, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS, FORGED_GMAIL_RCVD,FREEMAIL_FROM,HTML_MESSAGE,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-qv1-f53.google.com (mail-qv1-f53.google.com [209.85.219.53]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Sat, 18 Apr 2026 06:07:11 +0000 (UTC) Received: by mail-qv1-f53.google.com with SMTP id 6a1803df08f44-8aca0469204so15448676d6.2 for ; Fri, 17 Apr 2026 23:07:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1776492426; cv=none; d=google.com; s=arc-20240605; b=MtVXxUQhB8DTqnZ4CqXHDtHNopCPosar+TR5UxJoKWhtI+M9IvPKQ/FToFtDXaM9x1 MNy8zjTwGxs+Jj2oUgIQaKqdxnJX65Jcg9wbpThGf0wq3zz5VKHf6tbj6jgh+hbMI8S5 GsIppmwZdQEF4WIbThKAEITbLeN4orB4BIg7fIoG/S0zo99FymHDrcrSRJDIM/oBEEtE vaOLyybRoQcV/F+IbsGSQKkrtK0xeZSV9nmjTagWl6WdcixfeVw6yC4aB195gWMc5l5W RIpx+CZtroqKr3e2VnMWYAyxCArG5puhRvL4VVYD9uSrRS9SYBWLWdBXQnqhCcDINq7d 7qlA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :dkim-signature; bh=tnm6I5j6Ej1GRL4UGa5n8RDOSCFu6EbPq2haTxxta38=; fh=RnZ+4KjfdZdxwVfzmjFoBvUAaJ227RJecqE9MM9tvfQ=; b=Cnr/fKn7hU6ljxxhTcju+s1W+pKDUhR8M4aPoaM1VAqW2qWfkZ2cv7Wat2UN8EpjYC T4/pGg53m+TlsMGZ2LM7E7XpzIFCYEuUGD4WF0wF1RUB4vlYhDthU/LYhL4P42509lbV dxkLsVyLiEjA8L1MftUWyHTCB+h7WLgMvQyYwOKxXhpscE+3wii/+tflJlsUjyxp9SdX eAeLt87MizJ3ZwQqJyZgu31CGQTgKVtFVv0hcjmXrSmiX/MO13RjCtZWN/pEBbmffgDf 28UJefDsEUUbXxp9eEsTA9cWeWOq4xUA3AuCsWqyg0Bnno7ksHnBWW6sXgqOvpveVm10 9OgA==; darn=lists.php.net ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776492426; x=1777097226; darn=lists.php.net; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date:message-id:reply-to; bh=tnm6I5j6Ej1GRL4UGa5n8RDOSCFu6EbPq2haTxxta38=; b=ZKLRR96O8NcZ96GgWdSCxOdaWlAeuws6QqvIERXEWUFwWKrFa/It8GJuLtp2X4bOLF VTr2IgXVPtCh3qudRLIBNRAlwDnqgNDNagHV7o2h0oe3zgT5soIkyQKrwxFhphUXI3RA mJ+coNbd6jcPPKui23fwK+Ukl/550H11aqc0txRy8Hyp1zbvm7YUYT9n5Xil5aDEzvFf 4omD40u5LSLbS22yDN79hk0Pfybk3qo/1U+l+ftfxhkPKiQZ1Bg+UJ1Znv7fgxVOg7dv //a/moTVeyr8OzW62HUTXOrfb13Qc9z7+mEhZx0k1e1N0/Z39pGGjBt+S66bz5o4Ldbf gPCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776492426; x=1777097226; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=tnm6I5j6Ej1GRL4UGa5n8RDOSCFu6EbPq2haTxxta38=; b=OlCZOPgYCMZVk1DEwZ8T9HktwfTcfE3kZs0/PwJUMraA7trINvEqPTWGX23JPVQJUJ mw8MRE9vaLLupgItZHxzJxsxFZM2RQp6M0Cjnp5nUSP/BTbnFbHINoYw3wY32brOvyZv frdX2K+xA+AdU8e8zf3qrO5P86uKCySzszkwCGzlwao6BsooqgsE1Y9DYDk5X89a/A7M h7wo75Zpwoq8RJFjiEa6YBnHnIC7TrV8Zpgf4vzmSsG74psKVfsXEcFmwMKhIKTQOoFr PDvR4dl4xZgcj6btTDcy6zxe0Lpo3zu2HazuhyXBHc5ksgmsrLzXS9j7Jp4Lms49A2BM QGhw== X-Gm-Message-State: AOJu0YyYi2gt+Ye0gJYneRPW1TsciVgg5sI4d3T1QGiR9uAh3V8dcgPK pHs3Cj8B8Xtdl0+BJtUHROZ8WmBrgJJqCt8LqgVEHOMLp/VozUob1Bjct9PvdcKyHOy1Ssjjohd 32XW4sEmNVcV0C+l7e71QjNyIaqibvjMyTpT7 X-Gm-Gg: AeBDieuERkpLa6N01bc0fzCsGswG4pEXL/2yjBAPEkvmUsqL6559XQoBQthNF6bW0Rz wJxCdrmGeIzeL8nUv/e+ZsfpxHAfw/ziDETa8L8ot5zpZcp9mlmPvgwqg6HMAOKN8a+9kfRfjQX LoEFwkTSv7bzD3JKb4Z39BNK9RWCGlCpJw3eoyjhYi9l0d6QyIKa9LuD7dMBiVUnh8FC+8P+fsw ClxQUvsIdGF5VV96+nMstFL15Y3CaG1JYb3OHN/BO91pMdLXH+CPkD98IM5wRo2TujXPVyl66vK /Db25f9OqINOGzwXa+9shPk68ydfhvupIIt2VB/5LLZGYkJy X-Received: by 2002:ad4:5ae4:0:b0:8ac:7e8d:8599 with SMTP id 6a1803df08f44-8b028036dd0mr101609866d6.20.1776492425517; Fri, 17 Apr 2026 23:07:05 -0700 (PDT) Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 References: <19d58a46b50222b75da4e40e417efd05@bastelstu.be> In-Reply-To: <19d58a46b50222b75da4e40e417efd05@bastelstu.be> Date: Sat, 18 Apr 2026 08:06:54 +0200 X-Gm-Features: AQROBzCmMpcyttgkWFHdvm17i8cLRYCtgGcCZHzu5zE8M490ViJjjC1G3KURl64 Message-ID: Subject: Re: [PHP-DEV] [RFC] [Discussion] array_get and array_has functions To: php internals Content-Type: multipart/alternative; boundary="000000000000f820ce064fb5df58" From: barel.barelon@gmail.com (Barel) --000000000000f820ce064fb5df58 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Wed, 15 Apr 2026 at 20:18, Tim D=C3=BCsterhus 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 =E2=80=9Cg= et=E2=80=9D as > the default operation, e.g. it's `array_first()`, not > `array_get_first()`. And for =E2=80=9Cexistence checks=E2=80=9D there's t= he 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 =E2=80=9Cisset=E2=80=9D-like semantic= s 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 =E2=80=9Cthrowing an error=E2=80=9D is always a safe option. > > But saying that `array_get_path(['foo' =3D> '???'], ['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 --000000000000f820ce064fb5df58 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
On Wed, 15 Apr 2026 at 20:18, Tim D=C3=BC= sterhus <tim@bastelstu.be> wr= ote:
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()

=C2=A0From what I see, the functions in the array API don't mention =E2= =80=9Cget=E2=80=9D as
the default operation, e.g. it's `array_first()`, not
`array_get_first()`. And for =E2=80=9Cexistence checks=E2=80=9D 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 th= e function name reads less naturally, but I agree that it improves discover= ability 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 t= he function names to `array_path_get` and `array_path_exists`. I have prefe= rred to keep `get` in the function name because I think that `array_path` i= s less clear about what the function does. RFC and implementation have been= updated.
=C2=A0

> - 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 y= ou may have
> something like:
>
> database:
>=C2=A0 =C2=A0 =C2=A0config: ~
>
> 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', 'c= onfig',
> 'port'],
> 7766), you want to get 7766, not an exception or error. Tim points out=
> that
> intermediate segments might be objects which implement ArrayAccess, bu= t
> allowing this would complicate the code of the function a lot without =
> much
> practical gain.

Perhaps the right solution is using =E2=80=9Cisset=E2=80=9D-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 =E2=80=9Cthrowing an error=E2=80=9D is always a safe option.

But saying that `array_get_path(['foo' =3D> '???'], [= 9;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":

=C2=A0 =C2=A0 =C2=A0database:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0connection: "mysql://root@db.example.com"

when in reality the library expects separate components:

=C2=A0 =C2=A0 =C2=A0database:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0connection:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0driver: mysql
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0host: db.example.com
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0user: root

Now extracting the host with `array_get_path($config, ['database', =
'connection', 'host'], 'localhost')` would erroneou= sly 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 cle= ar. And I don't really like the function throwing errors for paths, I t= hink 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. T= he existing implementations in Laravel=C2=A0and Lodash do not throw any err= or if an intermediate value is not an array (or object for Lodash) and inst= ead return the default, so I think it is best to keep this behaviour
<= div>
Cheers

Carlos=C2=A0
= --000000000000f820ce064fb5df58--