Re: Pre-RFC Discussion: Support for String Literals as Object Properties and Named Parameters in PHP
| From: | Mike Schinkel | Date: | Mon, 02 Sep 2024 14:51:16 +0000 |
| Subject: | Re: Pre-RFC Discussion: Support for String Literals as Object Properties and Named Parameters in PHP | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-125389@lists.php.net to get a copy of this message | ||
> On Sep 1, 2024, at 5:47 PM, Hammed Ajao <hamiegold@gmail.com> 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!
I know if it not exactly what you asked for, but have you considered using Enums and Attributes
instead?
Here is a working single file example of what I am suggesting:
https://gist.github.com/mikeschinkel/b71beb8b7ee626ba9e6ea4afaba11e22
I know it is more boilerplate, but does it address the same issues you were trying to address, or
not? If not, in what ways does not not address your use-cases?
I know it uses arrays which you seem to want to avoid, but it only uses they are the result of
operations on an enum which are not arrays that you need to maintain in your code.
Are there other use-cases besides working with HTTP header where Enums and Attributes would not
address the issues you were trying to address?
Generally I am one who welcomes new feature ideas, but I fear that string literals as object
properties would break a valuable assumption that all properties must be a valid identifier. Without
that assumption I fear many things that would become more complex.
Also there are chances such a change could break a lot of userland code that makes that same
assumption. I know from using MySQL where field names do not need to be valid identifiers that such
a "feature" complicates coding, makes certain bugs easier to create, and often makes code
less elegant (read "uglier") that it would otherwise be.
So I am sympathetic to the desire to improve the language. However I fear this specific change would
create more pain than pleasure. Better IMO to look for less disruptive solutions to achieve the same
goals. For example, if the Enum+Attributes approach meets your needs aside from having too much
boilerplate, maybe we could enhance PHP to have less of that boilerplate?
-Mike
P.S. I want to (again) thank those who brought us Enums as I think they are one of the best new
features PHP has added in the past decade. #fwiw