Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129192 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 E9C111A00BC for ; Mon, 10 Nov 2025 20:55:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1762808153; bh=xQJbozer1HoQ9A74pd/gccWoPuTvEPfb1jD0puM4uK0=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=W6vZcI3U+79hn4Ff1CiWT/0rUq9r1T5mRqiXje7VVP9Z2VylgJ8BHtA8+ZhN7k2yd ZmMW7y/lVTIOsGDPTY6cbdWhOhK9XxXJ6Kqodg/UagcLShbJvqtKEbVpt0dIaVDlEV 29t+AadqCK/YU2MorYpK7jeBc8VrQw1f8Xd690zdsLHP31YSvhnK4k/U25+cEbgamD k92nURYNSkfTvKazhcq9kALygyocaD8FfFAhz1eR8h3S6rAJgYHrroBIudAkNibdPG 0fRHE0Me/BE6Jmj0w94XGiTR/cKnX1PLFpeODQp+23IogqfoWbhBKOgFb99WfQUxVj OBBchjDZM7yZA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id B98031801D5 for ; Mon, 10 Nov 2025 20:55:52 +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=0.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,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-wm1-f47.google.com (mail-wm1-f47.google.com [209.85.128.47]) (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 ; Mon, 10 Nov 2025 20:55:52 +0000 (UTC) Received: by mail-wm1-f47.google.com with SMTP id 5b1f17b1804b1-475ca9237c2so19200295e9.3 for ; Mon, 10 Nov 2025 12:55:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1762808146; x=1763412946; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=YUjHP4Ypx1PU0yM0w+qvNmU20x13B1lYcdeoqhJzzk8=; b=MyGtCiNl0bEXI3JOzjlGVzufzeMq7Ci5Zh5v3bTOh/bj/cQDRMJvDUpccGE4iKMj2A abxHMYLqNQGUfjSwiEuZxelskezsETcVLY2IRV8a6sscqc9kdULYDLsOSQ6cYRtzCkvF NVocgZ9fMTFAEx91Ic3MCUvbmHGZE25oDgraa85X6s64yNKLYSEK4KW9GkJIRmzW95dx YZDefRDIigsSFxJMtyLkW0TB54Dd92y1GwDbt06w/HcexQyKjjx1YzeTx9Dia7+Leq/I seX069elVagkmrnFp7inS0mJpU+Nmb6FFAt7UNJNL/QaUxcj9qbvUY+gMmIp4NpIaCaS OwnA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762808146; x=1763412946; h=cc: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=YUjHP4Ypx1PU0yM0w+qvNmU20x13B1lYcdeoqhJzzk8=; b=rs4mkdaSnUsYmscHjcNbjTgA52VYLIU8K3KHL9gXww7gcYdVmnHqywnFsumnUnIkdQ +mh+bYsC3uSeHZ/Z28COLov5e837n3GPjI0YF7CHGpdYHqhLJtQ6wnnjD5/3apg0i5FN kh14NCibYofO2Z8dyjVIwytRKoPYmGjkRcwugmsv/mv2Shsy08wasdiZo5s5FVT7uw92 8uMYjh+DBBP927sdeVNBwrwKaNHFvPTIyBmG0QpjH4cl9+Od+OIQqt8bE5hOUqClGiYJ uBqefEPO1zd5D9qUYZnaIHuNpkT8L8rw8PoEXDMNHbk6pxx8nx82lugw9JucG6OkD50g Nluw== X-Gm-Message-State: AOJu0YxTaTC4rR64ilLXiFPdee5yp0lm7j2/gUFbIspOMH5Pd9rIXoIO BBKj3NgTFyElWxMe9Z1abY2mpjNO71nmOcUiyGJZLBGsBgAgvVcPzga9X6z0gqnt1hBYOOdDTd6 HRMOBqPwYA7Esa4egRkDSP8zNQVPkjQ== X-Gm-Gg: ASbGncsDxX+hXARvIG1KcVoWbc0ZwE2i710qYatxVTK63A8UgXWNqnuTyw+qOBOvEnR eBNDWBePzxurTzV9FcGmoMrnt9fph0Vr5r6ZNrAXBM8vvO8GyYmWcqhiXeNlCv5ud9x9FjHtVnK OPhL3Mkd18EJIjVy2nQySCDTwQtJRZExAnlO8D6HE2nTJrZKAV4vcx1V/XJ1kKZV6mjtySxC/hn Cc6MA4NtTQCGy/n1y+pmFVnzHyb4jg46TnR5l4jre7ddH1IZm39y2s+9HnwQaxTupylB2Ibd1H3 f61V/B1RQ14L/A== X-Google-Smtp-Source: AGHT+IHSEMNHZpA3F36fss3/4DIdxmeoxjJHvEmpqz9dG4voVWW5qoNBU046+aDNI53p2cJvmDfAkKCpND+yMvW3LF8= X-Received: by 2002:a05:600c:474c:b0:477:55c9:c3ea with SMTP id 5b1f17b1804b1-4777329747emr76444365e9.35.1762808145986; Mon, 10 Nov 2025 12:55:45 -0800 (PST) Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 References: In-Reply-To: Date: Tue, 11 Nov 2025 00:55:35 +0400 X-Gm-Features: AWmQ_blPu1nzlqE_rYZhw_uPXmN2S7Jo0gg2qde-btBQKrq1qR1QBYi928ZaUgs Message-ID: Subject: Re: [PHP-DEV] [RFC] [Discussion] Add values() Method to BackedEnum To: Mikhail Savin Cc: php internals Content-Type: multipart/alternative; boundary="000000000000594a96064343c11d" From: udaltsov.valentin@gmail.com (Valentin Udaltsov) --000000000000594a96064343c11d Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable =D0=BF=D0=BD, 10 =D0=BD=D0=BE=D1=8F=D0=B1. 2025=E2=80=AF=D0=B3. =D0=B2 08:4= 4, Mikhail Savin : > Hi internals, > > I've created an RFC to add a native values() method to BackedEnum: > > https://wiki.php.net/rfc/add_values_method_to_backed_enum > > =3D=3D Summary =3D=3D > > The RFC proposes adding BackedEnum::values() that returns an indexed arra= y > of all backing values. The implementation uses conditional registration - > the native method is only added when the enum doesn't already define > values(), ensuring ZERO backward compatibility breaks. > > Key points: > * Native values() added automatically to new enums > * Existing enums with custom values() continue working unchanged > * Trait-based implementations are respected > * Libraries can maintain their implementation for older PHP versions > * Solves boilerplate problem (3,860+ implementations, ~24k-44k real > usage) > > Common use cases: > * Database migrations: $table->enum('status', Status::values()) > * Form validation: in_array($input, Status::values()) > * API responses: ['allowed_values' =3D> Status::values()] > > =3D=3D Implementation =3D=3D > > Working implementation with conditional registration: > https://github.com/php/php-src/pull/20398 > > The engine checks if values() exists before registering the native versio= n: > - User-defined values() present? Use it. > - No user-defined values()? Add native implementation. > > =3D=3D No BC Breaks =3D=3D > > This approach ensures: > * Existing code works unchanged (no migration needed) > * Immediate benefit for new code (automatic values()) > * Gradual adoption possible (libraries can migrate at their pace) > > Trade-off: Makes values() the only overridable enum method (unlike > cases/from/tryFrom). The RFC documents this as a pragmatic choice - > solving real problems without forced migrations. > > =3D=3D Questions =3D=3D > > 1. Is the conditional approach technically sound? > 2. Is the API consistency trade-off acceptable given the zero BC breaks? > 3. Any concerns with the implementation approach? > 4. Should I implement some steps from "Future scope" of the rfc now? > > Discussion period: 2 weeks minimum before voting. > > Looking forward to your feedback! > > Best regards, > Savin Mikhail > Hi, Mikhail! Thank you for the RFC. Consider this code if this RFC is accepted: enum EnumWithUserDefinedValuesMethod: string { case X =3D 'x'; public static function values(): string { return 'values'; } } function getBackedEnumValues(BackedEnum $enum): array { return $enum::values(); } getBackedEnumValues(EnumWithUserDefinedValuesMethod::X); This code will suddenly break, because inside getBackedEnumValues I can safely assume that BackedEnum::values() returns an array, since it's a part of the interface contract. However, EnumWithUserDefinedValuesMethod breaks the Liskov Substitution Principle by defining a method with a non-compatible return type and gives a runtime error. What you've basically suggested is to ignore the LSP. This is not a good idea. -- Best regards, Valentin --000000000000594a96064343c11d Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
=D0=BF=D0=BD, 10 =D0=BD=D0=BE=D1=8F=D0=B1= . 2025=E2=80=AF=D0=B3. =D0=B2 08:44, Mikhail Savin <mikhail.d.savin@gmail.com>:
Hi internals,

I've created an RFC= to add a native values() method to BackedEnum:

https:/= /wiki.php.net/rfc/add_values_method_to_backed_enum

=3D=3D Summar= y =3D=3D

The RFC proposes adding BackedEnum::values() that returns a= n indexed array
of all backing values. The implementation uses conditio= nal registration -
the native method is only added when the enum doesn&= #39;t already define
values(), ensuring ZERO backward compatibility bre= aks.

Key points:
=C2=A0 * Native values() added automatically to = new enums
=C2=A0 * Existing enums with custom values() continue working = unchanged
=C2=A0 * Trait-based implementations are respected
=C2=A0 *= Libraries can maintain their implementation for older PHP versions
=C2= =A0 * Solves boilerplate problem (3,860+ implementations, ~24k-44k real usa= ge)

Common use cases:
=C2=A0 * Database migrations: $table->en= um('status', Status::values())
=C2=A0 * Form validation: in_arra= y($input, Status::values())
=C2=A0 * API responses: ['allowed_values= ' =3D> Status::values()]

=3D=3D Implementation =3D=3D

= Working implementation with conditional registration:
https://github.com/p= hp/php-src/pull/20398

The engine checks if values() exists befor= e registering the native version:
=C2=A0 - User-defined values() present= ? Use it.
=C2=A0 - No user-defined values()? Add native implementation.<= br>
=3D=3D No BC Breaks =3D=3D

This approach ensures:
=C2=A0 *= Existing code works unchanged (no migration needed)
=C2=A0 * Immediate = benefit for new code (automatic values())
=C2=A0 * Gradual adoption poss= ible (libraries can migrate at their pace)

Trade-off: Makes values()= the only overridable enum method (unlike
cases/from/tryFrom). The RFC = documents this as a pragmatic choice -
solving real problems without fo= rced migrations.

=3D=3D Questions =3D=3D

1. Is the conditiona= l approach technically sound?
2. Is the API consistency trade-off accept= able given the zero BC breaks?
3. Any concerns with the implementation a= pproach?
4. Should I implement some steps from "Future scope"= of the rfc now?=C2=A0

Discussion period: 2 weeks minimum before vot= ing.

Looking forward to your feedback!

Best regards,
Savin= Mikhail

Hi, Mikhail!
<= br>Thank you for the RFC.

Consider this code if th= is RFC is accepted:

enum EnumWithUserDefinedVa=
luesMethod: string
{ case X =3D 'x';

public static function values(): string
{
return 'values'= ;;
}
}

function= getBackedEnumValues(BackedEnum
$enum): array
{=
return $enum::values();
}

getBackedEnumValues(EnumWithUserDe= finedValuesMethod::X);

This code will suddenly break, because inside= =C2=A0getBackedEnumValues I can safely assume that BackedEnum::values() ret= urns an array, since it's a part of the interface contract.

However,=C2=A0EnumWithUserDefinedValuesMetho= d breaks the Liskov Substitution Principle by defining a method with a non-= compatible return type and gives a runtime error.

What you've basically suggested is to ignore the LSP. = This is not a good idea.

--

Best regards, Valentin
--000000000000594a96064343c11d--