-
Notifications
You must be signed in to change notification settings - Fork 195
Closed
Labels
type: feature request‘Nice-to-have’ improvement, new feature or different behavior or design.‘Nice-to-have’ improvement, new feature or different behavior or design.
Description
RFC for supporting both named parameters in PHP 8 and options arrays for previous versions of PHP
Given class Foo with two "options" in its constructor, string cacheKey and int cacheLifetime, this would give us the following behavior in PHP 8.0:
new Foo(
cacheKey: 'foo',
cacheLifetime: 123
);And the following behavior in PHP 7.4 and below:
new Foo([
'cacheKey' => 'foo',
'cacheLifetime' => 123
]);For this case, the class constructor would look like:
class Foo
{
public function __construct(
array $options = null,
string $cacheKey = null,
int $cacheLifetime = 1500
) {
// ...
}
}The following cases would throw exceptions:
// provide both options array and named parameters
new Foo(
['cacheKey' => 'foo', 'cacheLifetime' => 123],
cacheKey: 'bar',
cacheLifetime: 456
);
// provide both options array and ordered parameters
new Foo(
['cacheKey' => 'foo', 'cacheLifetime' => 123],
'bar',
456
);
// provide options as a named parameter with other named parameters
new Foo(
options: ['cacheKey' => 'foo', 'cacheLifetime' => 123],
cacheKey: 'bar',
cacheLifetime: 456
);
// provide empty options array as a named parameter with other parameters
new Foo(
options: [],
cacheKey: 'bar',
cacheLifetime: 456
);
// provide empty options array as the first argument with other parameters
new Foo(
[],
cacheKey: 'bar',
cacheLifetime: 456
);It's not possible (AFAICT) to throw exceptions in the following non-standard scenarios:
// provide null options as a named parameter
new Foo(
options: null,
cacheKey: 'bar',
cacheLifetime: 456
);
// provide null options as a named parameter
new Foo(
null,
cacheKey: 'bar',
cacheLifetime: 456
);
// provide options as a named parameter by itself
new Foo(
options: ['cacheKey' => 'foo', 'cacheLifetime' => 123],
);This behavior is done by checking if $options is an array and calling func_num_args(). Using a trait, we can guarantee standard behavior across all our classes:
trait OptionsArrayWithAdditionalParametersTrait
{
private function verifyOptionsArrayWithAdditionalParameters(
?array $options,
int $numArgs
) {
if (is_array($options) && func_num_args() > 1) {
throw new LogicException(
'Cannot supply options array with additional parameters'
);
}
}
}class Foo
{
use OptionsArrayWithAdditionalParametersTrait;
public function __construct(
array $options = null,
string $cacheKey = '',
int $cacheLifetime = 1500
) {
$this->verifyOptionsArrayWithAdditionalParameters(
$options,
func_num_args()
);
$this->cacheKey = $options['cacheKey'] ?? $cache;
$this->cacheLifetime = $options['cacheLifetime'] ?? $cacheLifetime;
}
}Pros
- Named parameters can be used in PHP 8
- This allows for typehinting and cleaner syntax
- There is still a usable interface for earlier PHP versions.
Cons
- Some of the possible constructor cases are non-standard
- this behavior may be considered hacky or strange
- it allows for classes to be constructed without typehints.
Metadata
Metadata
Assignees
Labels
type: feature request‘Nice-to-have’ improvement, new feature or different behavior or design.‘Nice-to-have’ improvement, new feature or different behavior or design.