Re: Pre-RFC Discussion: Support for String Literals as Object Properties and Named Parameters in PHP
| From: | Rob Landers | Date: | Tue, 03 Sep 2024 06:41:08 +0000 |
| Subject: | Re: Pre-RFC Discussion: Support for String Literals as Object Properties and Named Parameters in PHP | ||
| References: | 1 2 3 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-125405@lists.php.net to get a copy of this message | ||
On Tue, Sep 3, 2024, at 02:00, Hammed Ajao wrote:
>
>
> On Mon, Sep 2, 2024 at 1:50 PM Rob Landers <rob@bottled.codes> wrote:
>> __
>> On Sun, Sep 1, 2024, at 23:47, Hammed Ajao wrote:
>>> Dear PHP internals community,
>>> I hope this email finds you all well. I'd like to propose an idea that I believe
>>> could enhance PHP's flexibility and consistency, especially when working with string literals.
>>> I'm looking forward to hearing your thoughts and feedback on this proposal.
>>> Introduction
>>> I'm suggesting two enhancements to PHP that I think could make our lives as
>>> developers a bit easier:
>>>
>>> Support for String Literals as Object Properties
>>> Support for String Literals as Named Parameters in Function Calls
>>>
>>> The main goal here is to reduce our reliance on arrays and provide more intuitive ways
>>> to define and access data, particularly in scenarios like working with HTTP headers where we often
>>> deal with non-standard characters and strings.
>>> 1. String Literals as Object Properties
>>> Current Situation
>>> As we all know, we typically define and access object properties using standard
>>> identifiers:
>>> ```php
>>> class Foo {
>>> public string $contentType = "application/json";
>>> }
>>>
>>> $obj = new Foo();
>>> $obj->contentType = "text/html";
>>> ```
>>>
>>> But when we're dealing with data that includes non-standard characters or strings
>>> (think HTTP headers), we often end up using associative arrays:
>>> ```php
>>> $headers = [
>>> "Content-Type" => "application/json",
>>> "X-Custom-Header" => "value"
>>> ];
>>> ```
>>>
>>> I think we can all agree that this reliance on arrays can make our code less intuitive,
>>> especially when we're managing complex data structures.
>>> Proposed Enhancement
>>> What if we could use string literals as object property names? Here's what
>>> I'm thinking:
>>> ```php
>>> class MyHeaders {
>>>
>>> public function __construct(
>>> public string "Content-Type" = "application/json",
>>> public string "Cache-Control" = "no-cache, no-store,
>>> must-revalidate",
>>> public string "Pragma" = "no-cache",
>>> public string "Expires" = "0",
>>> public string "X-Frame-Options" = "SAMEORIGIN",
>>> public string "X-XSS-Protection" = "1; mode=block",
>>> public string "X-Content-Type-Options" = "nosniff",
>>> public string "Referrer-Policy" =
>>> "strict-origin-when-cross-origin",
>>> public string "Access-Control-Allow-Origin" = "*",
>>> public string "X-Custom-Header" = "value",
>>> ) {}
>>>
>>> public static function create(string ...$headers): self {
>>> return new self(...$headers); // Throws an error if an unknown named parameter
>>> is passed
>>> }
>>>
>>> public function dispatch(): void {
>>> foreach ((array) $this as $name => $value) {
>>> header("$name: $value");
>>> }
>>> }
>>> }
>>>
>>> $headers = new MyHeaders("Content-Type": "application/json",
>>> "X-Custom-Header": "value");
>>> // or
>>> $headers = MyHeaders::create("Content-Type": "text/html;
>>> charset=utf-8", "X-Custom-Header": "value");
>>> $headers->dispatch();
>>> ```
>>> This would allow us to include characters in property names that aren't typically
>>> allowed in PHP identifiers, like hyphens or spaces. I think this could make our code more readable
>>> and aligned with natural data representation.
>>> Benefits
>>>
>>> Greater Flexibility: We could create more natural and direct representations of data
>>> within objects.
>>> Enhanced Consistency: This aligns with the proposed support for string literals as
>>> named parameters, creating a more uniform language experience.
>>> Simplification: It could reduce our need for associative arrays, which can be more
>>> error-prone and less intuitive.
>>>
>>> 2. String Literals as Named Parameters in Function Calls
>>> If we're going to use string literals as object properties, it makes sense to also
>>> use them as named parameters, especially in constructors with promoted properties. And why stop at
>>> constructors? This leads to the second part of my proposal.
>>> Current Situation
>>> We can use named parameters in function calls, but only with standard identifiers:
>>> ```php
>>> function myHeaders(...$args) {
>>> foreach ($args as $key => $value) header("$key: $value");
>>> }
>>> ```
>>>
>>> To use string literals with special characters, we have to use associative arrays:
>>> ```php
>>> myHeaders(...["Content-Type" => "application/json"]);
>>> ```
>>>
>>> This can be a bit cumbersome and less readable, especially for complex data structures.
>>> Proposed Enhancement
>>> What if we could use string literals as named parameters? It might look something like
>>> this:
>>> ```php
>>> foo("Content-Type": "application/json");
>>> ```
>>>
>>> I think this syntax could offer several advantages:
>>>
>>> Improved Readability: Our code could become clearer and more aligned with natural data
>>> representation.
>>> Automatic Parameter Mapping: We could map string literals to corresponding parameters
>>> without requiring manual intervention.
>>> Simplified Constructor Usage: This could be especially beneficial for constructors
>>> where we need to pass complex data structures directly.
>>>
>>> Implementation Considerations
>>> Of course, implementing these changes would require some work:
>>>
>>> The PHP engine would need to accommodate string literals as valid property names and
>>> named parameters, both at runtime and in class/function definitions.
>>> We'd need to carefully manage compatibility with existing code to ensure
>>> traditional property access remains unaffected.
>>> We'd need to decide whether to allow string literals as parameters in
>>> function/method declarations or only in function calls (to be retrieved by func_get_args() or
>>> variadic functions), with exceptions for constructors with promoted properties.
>>>
>>> I'm really interested to hear what you all think about this proposal.. Do you see
>>> potential benefits or challenges that I might have overlooked? How do you think this could impact
>>> your day-to-day coding?
>>> Looking forward to a great discussion!
>>> Best regards,
>>> Hammed
>>
>> Hey Hammed,
>>
>> This gets into the parser and its definition of "LABEL" (below PHP's
>> syntax):
>>
>> LABEL [a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*
>>
>> This means the first letter must be alpha-numeric ascii, or higher. And you can actually
>> just use the latter part and whatever encoding your file is (usually utf8):
>>
>> For example, this is valid PHP:
>>
>> class HTML {
>> public string $Content–Type;
>> public string $ዐxl;
>> public string $𝟷0sm;
>> }
>>
>> https://3v4l.org/KgJKm
>>
>> You can also use emojis or look-alikes as much as you want. It's not a direct answer
>> to what you are seeking, but it gets pretty close.
>>
>> — Rob
> Hi Rob,
>
> That's actually pretty neat, but it starts to fall apart when you need the unicode
> representation e.g. converting to json :https://3v4l.org/VXfDl .
>
> Hammed
Hey Hammed,
You'll still need to do a conversion of some type; luckily, someone else maintains a list: https://github.com/codebox/homoglyph/blob/master/raw_data/chars.txt
I briefly looked into allowing this last night and allowing properties like this would allow
everything to have a full string representation. This would be valid:
$"fancy-thing" = other fancy thing.
The thing is, we kinda already allow it through variable-variables and other means, as this is all
valid php: https://3v4l.org/nFBeV
So, if I understand correctly, you are seeking a syntax to allow for defining the properties without
using dynamic properties?
Currently, you can access the property like this:
$this->{'my-invalid-prop'}
So, why not embrace what already exists instead of trying to change the syntax drastically? So, like
this, maybe?
public string {'my-invalid-prop'};
Allowing this appears to be on the grammar level of the language, meaning it is probably a
straightforward change.
— Rob