[PHP-DEV] Pre-RFC Discussion: Support for String Literals as Object Properties and Named Parameters in PHP

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:
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:

$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:

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.

  1. 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:
function myHeaders(...$args) {
foreach ($args as $key => $value) header("$key: $value");
}

To use string literals with special characters, we have to use associative arrays:

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:

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

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:

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:

$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:

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:

function myHeaders(...$args) {
    foreach ($args as $key => $value) header("$key: $value");
}

To use string literals with special characters, we have to use associative arrays:

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:

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:

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

On 02.09.2024 at 16:51, Mike Schinkel wrote:

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.

Is that so? See <https://3v4l.org/bZTFi&gt;\.

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?

ACK

Christoph

On Sep 2, 2024, at 12:42 PM, Christoph M. Becker <cmbecker69@gmx.de> wrote:

On 02.09.2024 at 16:51, Mike Schinkel wrote:

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.

Is that so? See <https://3v4l.org/bZTFi>.

Consider me corrected.

I seem to now remember once knowing this was possible since you point it out. I think my subconscious must have caused me to repress that memory given the tragedy of it when I read Hammad’s proposal. ¯_(ツ)_/¯

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?

ACK

Can you elaborate on what ‘ACK’ means in this context?

-Mike

Hello Mike,

Thanks for reading and responding. While your enum does technically address some of the issues I am discussing, it does so in a very verbose and cumbersome way.

  • First you need the DefaultValue attribute
  • Then you need to use it on each of your properties
  • You also need to define an identifier for the const which defeats the purpose of using literal strings
  • Then you need to use reflection to access the properties
  • Then you’re left with : MyHeaders::create(MyHeaders::CONTENT_TYPE, “plain/text”, MyHeaders::X_CUSTOM_HEADER,“new_value”); which isn’t super clear that it’s mapping every other value to the one before it.

As for the idea that an object property must be a valid identifier, I’m not sure that’s correct. Objects can have integer properties natively i.e $obj->{1}, and literal string properties are already possible when you cast an array to an object

Let me show you a few other use cases i’ve run into


class Sizes {
public function __construct(
private string $sm,
private string $md,
private string $lg,
private string $xl,
private string $2xl, // will throw
private string "10xl", // wouldn't this be nice
) {}
}

function htmlElement(string $tag, string $content, string|bool ...$attr) {}
htmlElement("div", "Hello, world!", class: "greeting", id: "greeting", "data-foo": "bar");

Cheers,
Hammed.

On Mon, Sep 2, 2024 at 8:51 AM Mike Schinkel <mike@newclarity.net> wrote:

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:
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:

$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:

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.

  1. 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:
function myHeaders(...$args) {
foreach ($args as $key => $value) header("$key: $value");
}

To use string literals with special characters, we have to use associative arrays:

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:

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

On 02.09.2024 at 19:35, Mike Schinkel wrote:

On Sep 2, 2024, at 12:42 PM, Christoph M. Becker <cmbecker69@gmx.de> wrote:

On 02.09.2024 at 16:51, Mike Schinkel wrote:

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?

ACK

Can you elaborate on what 'ACK' means in this context?

That I fully agree to your statement. (Seems this term might be more
common in German newsgroups. :slight_smile:

Christoph

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:


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:


$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:


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.

  1. 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:


function myHeaders(...$args) {

foreach ($args as $key => $value) header("$key: $value");

}

To use string literals with special characters, we have to use associative arrays:


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:


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

On Sep 2, 2024, at 1:48 PM, Hammed Ajao <hamiegold@gmail.com> wrote:

Hello Mike,

Thanks for reading and responding. While your enum does technically address some of the issues I am discussing, it does so in a very verbose and cumbersome way.
- First you need the DefaultValue attribute
- Then you need to use it on each of your `properties`
- You also need to define an identifier for the const which defeats the purpose of using literal strings
- Then you need to use reflection to access the properties
- Then you're left with : MyHeaders::create(MyHeaders::CONTENT_TYPE, "plain/text", MyHeaders::X_CUSTOM_HEADER,"new_value"); which isn't super clear that it's mapping every other value to the one before it.

That is why I wrote that maybe we could consider reducing the verbosity and more cumbersome aspects as I proactively recognized it was painful.

That is why I asked about other use-cases. If the only solid use-case is HTTP headers we write it once and its done.

OTOH, if there are many other use-cases then we could look at adding syntax sugar. Adding syntax sugar to languages when boilerplate patterns emerge has many benefits: fewer bugs, easier coding, making the language more powerful, and etc.

As for the idea that an object property must be a valid identifier, I'm not sure that's correct. Objects can have integer properties natively i.e $obj->{1}, and literal string properties are already possible when you cast an array to an object

Yes, that was pointed out to me.

I was thinking more about the PHP language for language parsers syntax when I wrote that and thinking less about the fact that instances can have dynamically assigned properties. My bad.

Let me show you a few other use cases i've run into

```php

            class Sizes {
                public function __construct(
                    private string $sm,
                    private string $md,
                    private string $lg,
                    private string $xl,
                    private string $2xl, // will throw
                    private string "10xl", // wouldn't this be nice
                ) {}
            }

Is that really a class that someone would write, with a different property for each size and a constructor that required setting each size? Or wouldn't they typically have an Enum for the sizes and an array property indexed by the enum?

Maybe your example was just to illustrate your desire for a `$2xl` and `"10xl"` property? I see what you want here, OTOH I would not be a fan. I'm just as happy to name them `$twoXL` and `$tenXL`, or `$_2xl` and `$_10xl` vs. dealing with non-identifiers in declared property names. I get that is not what you want, but realize I am not the decider, I am just representing one person's opinion, and I can't even vote on RFCs, so there is that. ¯\_(ツ)_/¯

            function htmlElement(string $tag, string $content, string|bool ...$attr) {}
            htmlElement("div", "Hello, world!", class: "greeting", id: "greeting", "data-foo": "bar");

I did not grasp the use-case you are showing here because the one in your original email included using non-identifiers as parameter names so I conflated your two proposals as being one.

In the case you presenting here —assuming I understand what you are proposing — I would likely be in favor of something like it. That is if it were orthogonal and not requiring of your first proposal i.e. in its own RFC.

Taking what you have I would expect something more like the following but where `[HtmlAttribute]` is my placeholder for a syntax that would specify that zero or more named parameters be collected and assigned by property name to the object `$attr` of type `HtmlAttribute` — bikeshed away on that syntax —, and to assign to arrays you specify the array index in the named argument, e.g. `data["foo"]`:

class HtmlAttribute {
   public string $_class;
   public string $id;
   public array $data;
}
function htmlElement(string $tag, string $content, [HtmlAttribute] ...$attr) {}
htmlElement("div", "Hello, world!", class: "greeting", id: "greeting", data["foo"]: "bar");

Alternately if you were not envisioning the mapping to an object a similar feature could just be way to use a function to collect arbitrarily names parameters into an array, e.g.:

function htmlAttributes(string|int ...$attr) {}
htmlAttributes(class: "greeting", id: "greeting", data["foo"]: "bar");

The above would collect the args into an array `$attr` shaped like this:

array(
   "class" => "greeting",
   "id" => "greeting",
   "data" => array(
     "foo" => "greeting",
   ),
);

Actually, it would be nice if PHP offered both options.

- Then you're left with : MyHeaders::create(MyHeaders::CONTENT_TYPE, "plain/text", MyHeaders::X_CUSTOM_HEADER,"new_value"); which isn't super clear that it's mapping every other value to the one before it.

BTW: it could currently be written like any of the following:

// 2-element arrays represents name-value pairs
public static function create(string ...$headers): self {...}
MyHeaders::create(
  [MyHeaders::CONTENT_TYPE, "plain/text"],
  [MyHeaders::X_CUSTOM_HEADER,"new_value"]
)

// 1-element arrays w/key and value represents name-value pairs
public static function create(string ...$headers): self {...}
MyHeaders::create(
  [MyHeaders::CONTENT_TYPE => "plain/text"],
  [MyHeaders::X_CUSTOM_HEADER =>"new_value"]
)

// 1-element array w/multiple elements represents name-value pairs
public static function create(array $headers): self {...}
MyHeaders::create([
  MyHeaders::CONTENT_TYPE => "plain/text",
  MyHeaders::X_CUSTOM_HEADER =>"new_value"
])

Alternately imagine some syntax sugar that allows dropping the `MyHeaders::` from the enum reference when a parameter is declared to be an instance of that enum:

// Objects represents name-value pairs
Header(MyHeaders $header, string $name):array {...}
public static function create(Header ...$headers): self {...}
MyHeaders::create(
  Header(CONTENT_TYPE, "plain/text"),
  Header(X_CUSTOM_HEADER, "new_value")
)

Finally imagine adding a feature that allows specifying that a parameter is the result of a function call give brace enclosed parameters where `Header(*)` is my placeholder syntax for bikeshedding, e.g.:

// Objects represents name-value pairs
public static function create(Header(*) ...$headers): self {...}
MyHeaders::create(
  { CONTENT_TYPE, "plain/text" },
  { X_CUSTOM_HEADER, "new_value"}
)

#fwiw

-Mike

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:


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:


$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:


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.

  1. 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:


function myHeaders(...$args) {

foreach ($args as $key => $value) header("$key: $value");

}

To use string literals with special characters, we have to use associative arrays:


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:


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

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:


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:


$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:


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.

  1. 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:


function myHeaders(...$args) {

foreach ($args as $key => $value) header("$key: $value");

}

To use string literals with special characters, we have to use associative arrays:


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:


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

On 02/09/2024 19:42, Christoph M. Becker wrote:

On 02.09.2024 at 16:51, Mike Schinkel wrote:

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.

Is that so? See <https://3v4l.org/bZTFi&gt;\.

And it works with methods too, you just can't define them but can catch with __call:

<?php

class AAA {
     public function __call(string $name, array $arguments)
     {
         var_dump($name);
     }
}

[new AAA, '123AnyChars%%!@#']();

On 03/09/2024 14:48, Anton Smirnov wrote:

[new AAA, '123AnyChars%%!@#']();

Wrong example, sorry, should be

(new AAA)->{'123AnyChars%%!@#'}();

On Sep 3, 2024, at 7:52 AM, Anton Smirnov <sandfox@sandfox.me> wrote:

On 03/09/2024 14:48, Anton Smirnov wrote:

[new AAA, '123AnyChars%%!@#']();

Wrong example, sorry, should be

(new AAA)->{'123AnyChars%%!@#'}();

Still, '123AnyChars%%!@#' is not included in the array returned by `get_class_methods()` and/or `ReflectionClass::getMethod()` which is evidence of why procedural magic methods are at best a bandaid compared with declarative solutions.

-Mike

On Sep 2, 2024, at 11:10 PM, Hammed Ajao <hamiegold@gmail.com> wrote:

That's one of the reasons, but arrays are not strict enough (you can add anything to any array, no distinction between a list and map), and you can't really specify the shape of an array.

What do you mean by "shape of an array" in this context?

I am trying to understand how an object differs in "shape" and I am coming up with nothing.

And/or do you want the compiler to validate when you use a name that has not been declared, i.e. when you type "Content_Type" or "Content Type" for <key> you want an error message?

The cool thing is that the compiler already does this with named parameters or the splat operator applied to an array (Online PHP editor | output for tholi).

That is quite interesting, I did not know that was possible.

Unfortunately though, the validation is done at the point of call not at the point of array instantiation which can result in spooky action at a distance if use in more than trivial ways:

Not at all, I just prefer custom and strict data structures with a clear intention.

+1

I mean it is more work having to define a custom attribute and reflecting It's target each time you want literal string names. The compiler already does all I need, I just want to extend that support to literal strings.

I'm proposing using a class every time you need a strict data structure with the keys known ahead of time, trust me i have no issue with more work when it's warranted, your version is just a lot of unnecessary code that doesn't actually achieve that.

Okay, I hear where you are coming from.

I'm proposing two things:
1. Properties keys as literal strings:

class A { public array "key"; }

Since php also allows declaring properties in functions (promoted properties), we have to decide what to do with:

class A { public function __construct(public array "key"); }

Which means we would run into cases where it's valid to pass a literal string as a named parameter

$a  = new A("key": 1);

I decided to add that to my proposal since there's no point restricting it to only constructors, which brings us to:
2. Literal strings as named parameters
Since I decided to include functions, we now have to decide what to allow and what not, for example, can you now define params as strings too:

function func(string "param", array "withDefault" = []) {}

or is it only allowed in variadic functions and func_get_args() (so syntactic sugar for what we have now with func(...))

That is very helpful to understand why you came to what you are proposing.

For me though, extending it in that way would potentially infect other much more common use-cases so I would prefer to have a constrained data type that allowed this rather than an open-ended one. And one that did not perpetuate the requirement to use quotes for what are effectively identifiers that do not follow the syntactical rules of identifiers.

Say I have a response class:

class Response { 
    public function __construct(private MyHeaders $headers) {}
}

With MyHeaders being a class, nothing is stopping me from passing in:

class MyCustomHeaders extend MyHeaders {
    public function __construct() {
        parent::__construct();
        //unset one of the keys or set more
    }
}

That isn't possible with the enum and I would have to store MyHeaders as an array in the Response class.

Fair point on the enum

OTOH as for storing as an array in your Response class, I don't see how that is huge issue. I do see how the array does not have a reflectable identity, but stuff it in a single property Response class and then together they do.

But I do get that you want to minimize that boilerplate.

> MyHeaders::create("Content-Type": "text/html; charset=utf-8", "X-Custom-Header": "value")

But it's clear, each key does what it intends, no additional processing will be required to transform/validate the keys.

It is only "clear" if you can get past all the quotes obscuring what is a key and what it a value.

When I first saw your proposal I did not notice the colons and thought you had written the following. If you read back at my original reply you'll recognize that I misunderstood your example:

MyHeaders::create("Content-Type", "text/html; charset=utf-8", "X-Custom-Header", "value")

IOW, I find it too easy to misread and would not want to have to read and/or maintain code that did not have a more easily visible distinction between what goes on the left of the colon and what goes on the right, remembering that reading and maintenance comprise far more time in the life of working code than the initial development.

MyHeaders::create(Content-Type: "text/html; charset=utf-8", X-Custom-Header: "value")

That works for me, but the literal has clearer intent and doesn't rely on transformation.

Clearer in your view, but not in mine.

Although I do concur that is requires a transformation I do not find that to be problematic as the rules would need to be determinative and would be easier to recognize key vs. value. Especially when reading code written by those darn developers who do not write each key:value pair on a new line of their own. :wink:

It would be interesting to know who else on the list thinks it is clear enough with the quote vs. those who would prefer a transform to avoid having to use quotes?

Are you sure what you are proposing would _not_ end up having to use reflection under the hood and be equally less performant?

Yep, it would be mostly handled in the parser/compiler, and internally, named params are already represented as a php array so we wouldn't even have to change much.

In your example which that I copied below for reference, how will `MyHeaders::create(...)` and `new self(...$headers)` work without reflection?

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();

For example, what if PHP had two new datatypes DataSet and DataPair (or some other bikeshed names) that allowed for defining a set of name-valued pairs, that could be optionally be close-end or open-ended, that could be converted to arrays or stdClass objects, that could be validated by the compiler for close-ended sets, that could be used to specify named arguments for functions, that do not need to use quotes for names, and probably other very flexible aspects? Wouldn't that be better than shoehorning features onto existing classes to handle your use-case? (DataSet and DataPair could be classes under the hood, just like Enums are.)

I would love more data types but that doesn't solve this issue.

I specifically crafted the idea of `DataSet` and `DataPair` to solve your issues, at least as I understand them. Consider the following hypothetical example:

<?php
    
closed dataset MyHeaders {
    public function __construct(
    public datapair Content-Type = "application/json",
    public datapair Cache-Control = "no-cache, no-store, must-revalidate",
    public datapair Pragma = "no-cache",
    public datapair int Expires = 0,
    public datapair X-Frame-Options = "SAMEORIGIN",
    public datapair X-XSS-Protection = "1; mode=block",
    public datapair X-Content-Type-Options = "nosniff",
    public datapair Referrer-Policy = "strict-origin-when-cross-origin",
    public datapair Access-Control-Allow-Origin = "*",
    public datapair X-Custom-Header = "value",
){}
    
    public static function create(datapair ...$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->current");
        }
    }
}
// Giving each header its own line so they are not so damn hard to read...
$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();

As I am proposing, the above defines a `closed` dataset meaning only the properties declared are valid. If declared as open-ended, keys assigned to an instance would not need to be validated in a constructor.

`datapair` properties and variables would be value objects with have a `->current` property and an `->original` property where the default value would gets assigned to `->original` and `->current`, but `->current can be overwritten (or `->value` and `->default` if `default` could be used in this context.)

Anything declared to be a `datapair` type could be declared to have names that are not valid identifiers and end with whitespace.

A declared `datapair` inner type would default to `string` but could be declared otherwise if needed, see how I declared `Expires` as `int`. However, it would be good if they could always just be `string` and never anything else.

By their nature, any dataset properties or variables would need to be accessed with braces, e.g. `$this->{Content-Type}` and `${Content-Type}` or if without quotes is not possible in the parser then by `$this->{'Content-Type'}` and `${'Content-Type'}`

Given the above — assuming it were accepted and added as a feature to PHP — how would this not address your use-case(s)?

Note I have no idea if the above would even be considered, but I am proposing here to understand what alternatives may be to address your desired use-case(s).

Good call, I should probably separate both proposals.

+1

-Mike