Re: [PHP-DEV] [Pre-RFC] Idea: named parameter lists

On 2026-08-18 10:12, Henrik Skov wrote:

Hi list !

Just got an idea:

params COOKIE_PARAMS {
time() + 3600, // Duration - NOTE: any expression is allowed here except pure variables
'/', // Path
'', // Can't remember what this is...
(! IS_DEV), // secure — set true once served over HTTPS (production)
TRUE, // httpOnly
'Lax', // Lax|Strict
}

Instead of this: (I am using Swoole)

    $response\->cookie\(
        self::COOKIE\_NAME,
        $token,
        time\(\) \+ 3600,
        '/',
        '',
        \(\! IS\_DEV\),     // secure — set true once served over HTTPS
        TRUE,           // httpOnly
        'Lax',
    \);

we could do:

    $response\->cookie\(
        self::COOKIE\_NAME,
        $token,
        :::COOKIE\_PARAMS
    \);

I know it is kind of similar to the spread operator but not quite.

What do you guys think ?Email:

PHP already has named parameters[0], and this can be combined with array unpacking[1] to produce basically the same as you're requesting here: Online PHP editor | output for kD27a

(Note: I've purposely moved the samesite parameter to prove the named array keys are mapping to the named function parameters, and not just working because they happen to be in order)

[0] PHP: Function parameters and arguments - Manual
[1] PHP: Arrays - Manual

Hi again !
The important part is that any instantiations and function calls are evaluated at call-time and not compile time !

So time() would return the timestamp at time of call and not when compiler first encounters the COOKIE_PARAMS const array. The new params keyword would make this clear to the compiler

/Henrik

var_dump(time()); // → 1787047284

···

On 18/08/2026 11.43, Henrik Skov wrote:

Thanks for the feedback.

Problem with your re-written example is that it works with/depends on global variables…

I was the code below actually worked:

<?php const COOKIE_PARAMS = [ "samesite" => "Lax", "expires_or_options" => time() + 3600, // Let's say time is 1787047184 "path" => "/", "domain" => "", "secure" => false, "httponly" => true, ]; function fakeSetCookie( string $name, string $value = "", int $expires_or_options = 0, string $path = "", string $domain = "", bool $secure = false, bool $httponly = false, string $samesite = "Strict", ) { var_dump([ "name" => $name, "value" => $value, "expires_or_options" => $expires_or_options, "path" => $path, "domain" => $domain, "secure" => $secure, "httponly" => $httponly, "samesite" => $samesite, ]); } sleep(100);

fakeSetCookie(“testName”, “testValue”, …COOKIE_PARAMS); so expires_or_options become 1787050884

But sadly, it does not work:

Fatal error: Constant expression contains invalid operations in /tmp/x.php on line 2

/Henrik

Med venlig hilsen

Henrik Skov
HSK Consulting
Blegdamsvej 128B, 4
DK-2100 Copenhagen O
Tel.: +45 27 62 83 01
Email: henry.wood.dk@gmail.com

On 18/08/2026 11.34, AllenJB wrote:

On 2026-08-18 10:12, Henrik Skov wrote:

Hi list !

Just got an idea:

params COOKIE_PARAMS {
time() + 3600, // Duration - NOTE: any expression is allowed here except pure variables
‘/’, // Path
‘’, // Can’t remember what this is…
(! IS_DEV), // secure — set true once served over HTTPS (production)
TRUE, // httpOnly
‘Lax’, // Lax|Strict
}

Instead of this: (I am using Swoole)

$response->cookie(
self::COOKIE_NAME,
$token,
time() + 3600,
‘/’,
‘’,
(! IS_DEV), // secure — set true once served over HTTPS
TRUE, // httpOnly
‘Lax’,
);

we could do:

$response->cookie(
self::COOKIE_NAME,
$token,
:::COOKIE_PARAMS
);

I know it is kind of similar to the spread operator but not quite.

What do you guys think ?Email:

PHP already has named parameters[0], and this can be combined with array unpacking[1] to produce basically the same as you’re requesting here: https://3v4l.org/kD27a#v

(Note: I’ve purposely moved the samesite parameter to prove the named array keys are mapping to the named function parameters, and not just working because they happen to be in order)

[0] https://www.php.net/manual/en/functions.arguments.php#functions.named-arguments
[1] https://www.php.net/manual/en/language.types.array.php#language.types.array.unpacking

Med venlig hilsen

Henrik Skov
HSK Consulting
Blegdamsvej 128B, 4
DK-2100 Copenhagen O
Tel.: +45 27 62 83 01
Email: henry.wood.dk@gmail.com

On 2026-08-18 11:02, Henrik Skov wrote:

Hi again !
The important part is that any instantiations and function calls are evaluated at call-time and not compile time !

So time() would return the timestamp at time of call and not when compiler first encounters the COOKIE_PARAMS const array. The new params keyword would make this clear to the compiler

/Henrik

On 18/08/2026 11.43, Henrik Skov wrote:

Thanks for the feedback.

Problem with your re-written example is that it works with/depends on global variables...

I was the code below actually worked:

<?php
const COOKIE_PARAMS = [
"samesite" => "Lax",
"expires_or_options" => time() + 3600, // Let's say time is 1787047184
"path" => "/",
"domain" => "",
"secure" => false,
"httponly" => true,
];

[...]

>>
>> sleep(100);
>>
>> var_dump(time()); // -> 1787047284
>>
>> fakeSetCookie("testName", "testValue", ...COOKIE_PARAMS); so
>> expires_or_options become 1787050884

Ah, I think I understand now.

What you're proposing is a structure where you can define a value as an expression, and that expression is only evaluated when the structure is used (rather than when it's defined).

So, even in a long-lived application, the expires_or_options value would always be evaluated as `time() + 3600`

If this were to be implemented, I think it would be better to look at values, rather than defining an entire structure. I can see it being used for more than parameters.

Something like an IIFE that's invoked when used rather than when defined.

As a side-note, one way to achieve this in current PHP would be to use a callable:

$params = function() {
     return [
         "samesite" => "Lax",
         "expires_or_options" => time() + 3600,
         "path" => "/",
         "domain" => "",
         "secure" => false,
         "httponly" => true,
     ];
};

fakeSetCookie("testName", "testValue", ...$params());
sleep(2);
fakeSetCookie("testName", "testValue", ...$params());

(3v4l refused to save this, probably because it takes too long)

This can also be written using arrow functions:

$params = fn() => [
     "samesite" => "Lax",
     "expires_or_options" => time() + 3600,
     "path" => "/",
     "domain" => "",
     "secure" => false,
     "httponly" => true,
];

On 18/08/2026 12.52, AllenJB wrote:

On 2026-08-18 11:02, Henrik Skov wrote:

Hi again !
The important part is that any instantiations and function calls are evaluated at call-time and not compile time !

So time() would return the timestamp at time of call and not when compiler first encounters the COOKIE_PARAMS const array. The new params keyword would make this clear to the compiler

/Henrik

On 18/08/2026 11.43, Henrik Skov wrote:

Thanks for the feedback.

Problem with your re-written example is that it works with/depends on global variables...

I was the code below actually worked:

<?php
const COOKIE_PARAMS = [
"samesite" => "Lax",
"expires_or_options" => time() + 3600, // Let's say time is 1787047184
"path" => "/",
"domain" => "",
"secure" => false,
"httponly" => true,
];

[...]

>>
>> sleep(100);
>>
>> var_dump(time()); // -> 1787047284
>>
>> fakeSetCookie("testName", "testValue", ...COOKIE_PARAMS); so
>> expires_or_options become 1787050884

Ah, I think I understand now.

What you're proposing is a structure where you can define a value as an expression, and that expression is only evaluated when the structure is used (rather than when it's defined).

So, even in a long-lived application, the expires_or_options value would always be evaluated as `time() + 3600`

If this were to be implemented, I think it would be better to look at values, rather than defining an entire structure. I can see it being used for more than parameters.

Something like an IIFE that's invoked when used rather than when defined.

As a side-note, one way to achieve this in current PHP would be to use a callable:

$params = function() {
    return [
        "samesite" => "Lax",
        "expires_or_options" => time() + 3600,
        "path" => "/",
        "domain" => "",
        "secure" => false,
        "httponly" => true,
    ];
};

fakeSetCookie("testName", "testValue", ...$params());
sleep(2);
fakeSetCookie("testName", "testValue", ...$params());

(3v4l refused to save this, probably because it takes too long)

This can also be written using arrow functions:

$params = fn() => [
    "samesite" => "Lax",
    "expires_or_options" => time() + 3600,
    "path" => "/",
    "domain" => "",
    "secure" => false,
    "httponly" => true,
];

--

Yes, but I think one should consider params COOKIE_PARAMS {...} more of a type !

Med venlig hilsen

Henrik Skov
/HSK Consulting/
Blegdamsvej 128B, 4
DK-2100 Copenhagen O
Tel.: +45 27 62 83 01
Email: henry.wood.dk@gmail.com

On Tue, 18 Aug 2026 at 12:35, Henrik Skov <henry.wood.dk@gmail.com> wrote:

On 18/08/2026 12.52, AllenJB wrote:

On 2026-08-18 11:02, Henrik Skov wrote:

Hi again !
The important part is that any instantiations and function calls are evaluated at call-time and not compile time !

So time() would return the timestamp at time of call and not when compiler first encounters the COOKIE_PARAMS const array. The new params keyword would make this clear to the compiler

/Henrik

On 18/08/2026 11.43, Henrik Skov wrote:

Thanks for the feedback.

Problem with your re-written example is that it works with/depends on global variables...

I was the code below actually worked:

<?php
const COOKIE_PARAMS = [
    "samesite" => "Lax",
    "expires_or_options" => time() + 3600, // Let's say time is 1787047184
    "path" => "/",
    "domain" => "",
    "secure" => false,
    "httponly" => true,
];

[...]

>>
>> sleep(100);
>>
>> var_dump(time()); // -> 1787047284
>>
>> fakeSetCookie("testName", "testValue", ...COOKIE_PARAMS); so
>> expires_or_options become 1787050884

Ah, I think I understand now.

What you're proposing is a structure where you can define a value as an expression, and that expression is only evaluated when the structure is used (rather than when it's defined).

So, even in a long-lived application, the expires_or_options value would always be evaluated as `time() + 3600`

If this were to be implemented, I think it would be better to look at values, rather than defining an entire structure. I can see it being used for more than parameters.

Something like an IIFE that's invoked when used rather than when defined.

As a side-note, one way to achieve this in current PHP would be to use a callable:

$params = function() {
    return [
        "samesite" => "Lax",
        "expires_or_options" => time() + 3600,
        "path" => "/",
        "domain" => "",
        "secure" => false,
        "httponly" => true,
    ];
};

fakeSetCookie("testName", "testValue", ...$params());
sleep(2);
fakeSetCookie("testName", "testValue", ...$params());

(3v4l refused to save this, probably because it takes too long)

This can also be written using arrow functions:

$params = fn() => [
    "samesite" => "Lax",
    "expires_or_options" => time() + 3600,
    "path" => "/",
    "domain" => "",
    "secure" => false,
    "httponly" => true,
];

--

Yes, but I think one should consider params COOKIE_PARAMS {...} more of a type !

Then why not create a type for it Online PHP editor | output for lNjSX

On 18/08/2026 14.17, Kamil Tekiela wrote:

On Tue, 18 Aug 2026 at 12:35, Henrik Skov<henry.wood.dk@gmail.com> wrote:

On 18/08/2026 12.52, AllenJB wrote:

On 2026-08-18 11:02, Henrik Skov wrote:

Hi again !
The important part is that any instantiations and function calls are evaluated at call-time and not compile time !

So time() would return the timestamp at time of call and not when compiler first encounters the COOKIE_PARAMS const array. The new params keyword would make this clear to the compiler

/Henrik

On 18/08/2026 11.43, Henrik Skov wrote:

Thanks for the feedback.

Problem with your re-written example is that it works with/depends on global variables...

I was the code below actually worked:

<?php
const COOKIE_PARAMS = [
     "samesite" => "Lax",
     "expires_or_options" => time() + 3600, // Let's say time is 1787047184
     "path" => "/",
     "domain" => "",
     "secure" => false,
     "httponly" => true,
];

[...]

sleep(100);

var_dump(time()); // -> 1787047284

fakeSetCookie("testName", "testValue", ...COOKIE_PARAMS); so
expires_or_options become 1787050884

Ah, I think I understand now.

What you're proposing is a structure where you can define a value as an expression, and that expression is only evaluated when the structure is used (rather than when it's defined).

So, even in a long-lived application, the expires_or_options value would always be evaluated as `time() + 3600`

If this were to be implemented, I think it would be better to look at values, rather than defining an entire structure. I can see it being used for more than parameters.

Something like an IIFE that's invoked when used rather than when defined.

As a side-note, one way to achieve this in current PHP would be to use a callable:

$params = function() {
     return [
         "samesite" => "Lax",
         "expires_or_options" => time() + 3600,
         "path" => "/",
         "domain" => "",
         "secure" => false,
         "httponly" => true,
     ];
};

fakeSetCookie("testName", "testValue", ...$params());
sleep(2);
fakeSetCookie("testName", "testValue", ...$params());

(3v4l refused to save this, probably because it takes too long)

This can also be written using arrow functions:

$params = fn() => [
     "samesite" => "Lax",
     "expires_or_options" => time() + 3600,
     "path" => "/",
     "domain" => "",
     "secure" => false,
     "httponly" => true,
];

--

Yes, but I think one should consider params COOKIE_PARAMS {...} more of a type !

Then why not create a type for ithttps://3v4l.org/lNjSX#vgit.master

--
Because it is not worthy of a full class.
By the same logic, why do we have enums ?
A class of constants works just as fine as an enum ?

Maybe I shouldn't have said 'type' - What I meant was language construct I think

Med venlig hilsen

Henrik Skov
/HSK Consulting/
Blegdamsvej 128B, 4
DK-2100 Copenhagen O
Tel.: +45 27 62 83 01
Email: henry.wood.dk@gmail.com

On Tue, Aug 18, 2026, at 9:07 AM, Henrik Skov wrote:

Yes, but I think one should consider params COOKIE_PARAMS {...} more of a type !

Then why not create a type for it Online PHP editor | output for lNjSX

--
Because it is not worthy of a full class.

I really don't understand why people keep saying this. What makes something "unworthy" of being a class? Classes are not expensive, at least not as expensive as people seem to think. A data construct doesn't need to be as righteous as Thor to be "worthy" of a class. Plus, in PHP, building new things on top of classes/objects (like enums) is way, way easier than new standalone constructs.

By the same logic, why do we have enums ?
A class of constants works just as fine as an enum ?

It does not, because it doesn't create a bounded space. Constants are just a shorthand for "any int" or "any string."

Maybe I shouldn't have said 'type' - What I meant was language construct I think

If what you're ultimately after is a "lazy value" that isn't evaluated until it is read, I could see a use for that. Binding it to "parameters" makes no sense, though. And in practice, such a feature would almost certainly end up build on top of either closures or objects anyway. (And closures themselves are just objects, in fact.)

--Larry Garfield

On 18/08/2026 16.54, Larry Garfield wrote:

On Tue, Aug 18, 2026, at 9:07 AM, Henrik Skov wrote:

Yes, but I think one should consider params COOKIE_PARAMS {...} more of a type !

Then why not create a type for ithttps://3v4l.org/lNjSX#vgit.master

--
Because it is not worthy of a full class.

I really don't understand why people keep saying this. What makes something "unworthy" of being a class? Classes are not expensive, at least not as expensive as people seem to think. A data construct doesn't need to be as righteous as Thor to be "worthy" of a class. Plus, in PHP, building new things on top of classes/objects (like enums) is way, way easier than new standalone constructs.

By the same logic, why do we have enums ?
A class of constants works just as fine as an enum ?

It does not, because it doesn't create a bounded space. Constants are just a shorthand for "any int" or "any string."

Maybe I shouldn't have said 'type' - What I meant was language construct I think

If what you're ultimately after is a "lazy value" that isn't evaluated until it is read, I could see a use for that. Binding it to "parameters" makes no sense, though. And in practice, such a feature would almost certainly end up build on top of either closures or objects anyway. (And closures themselves are just objects, in fact.)

It was a kind of lazy value (the lazy value being in essense a parameters array) I was after - if by lazy value you mean a value you would only change in one place and then it would affect all places where ...COOKIE_PARAMS are used (only 6 places in my current codebase but that's room even for the parameters not to be in sync)

/Henrik

--Larry Garfield

--

Med venlig hilsen

Henrik Skov
/HSK Consulting/
Blegdamsvej 128B, 4
DK-2100 Copenhagen O
Tel.: +45 27 62 83 01
Email: henry.wood.dk@gmail.com

On Tue, Aug 18, 2026 at 5:57 PM Larry Garfield <larry@garfieldtech.com> wrote:

I really don't understand why people keep saying this. What makes something "unworthy" of being a class? Classes are not expensive, at least not as expensive as people seem to think.

Slightly offtopic, but I will try to answer this question. By
"unworthy", most often people mean a cognitive overhead as I would
call it. It's not necessarily about technical expensiveness, even
though many people do think that adding an additional class will add
some technical overhead. It's more about perception. And also about
development complexity sometimes.

I could give numerous examples, but will stick to only one. Imagine
you have a function which should return not only "main" data, but also
some additional data which comes for free while processing the
original request. If we were forced to go the "right way", we would
need to introduce a separate Dto which will hold "main" and
"secondary" data. But adding a Dto for this single case may seem
"unworthy", because from a cognitive point of view it is much easier
to return an array of [$main, $secondary]. And later on the calling
side do the unpacking [$main, $secondary] = $this->myFunction(...).
And given that we have lots of tools today to describe this array on
PhpDoc-level for static analysis, this solution won't be worse than a
dedicated Dto in terms of proper data-structures. But still looking
simpler cognitive-wise than a dedicated Dto.