Skip to content

Add various return-typed getters to ParameterBag #45775

Closed
@arderyp

Description

@arderyp

Description

right now, ParameterBag has only a few getter options for fetching values:

get(): mixed
getAlpha(): string
getAlnum(): string
getDigits(): string
getInt(): int
getBoolean(): bool

For those of us using static analyzers like PHPStan, we often find ourselves having to add a bunch of manual type checking code to ensure that the parameter we are fetching is of a specified type. I see two main problems/annoyances here:

  1. In terms of fetching configuration parameters, this often means implementing type checks to ensure that the returned value is indeed the type that we already know it to be.
  2. In terms of fetching Request and Query parameters, we have to contend with the fact that forms cast everything to strings, which means fetching a mixed result from get(), type checking it as a string, then casting it to the actual type it should be.

The two exclusions here are getInt() and getBoolean(). Furthermore, getInt() is potentially dangerous with it's naked cast, as you may be fetching 5.5 or "5.5" and it will return 5 instead of throwing an exception.

Example

Would the community find it valuable to have many more typed getters along the lines of getInt() and getBoolean() that return validated parameters returned as their proper type? I'm thinking things along the lines of:

getArray(): array
getArrayOrNull(): ?array
getBoolean(): bool
getBooleanOrNull(): ?bool
getInt(): int
getIntOrNull(): ?int
getFloat(): float
getFloatOrNull(): ?float
getString(): string
getStringOrNull(): ?string

here are some quick examples, including an improvement of getInt():

protected function getInt(string $key, int $default = 0): int
{
    if (is_int($value = $this->get($key, $default))) {
        return $value;
    }
    throw $this->getException("int", $value);
}

protected function getIntOrNull(string $key, int $default = 0): ?int
{
    $value = $this->get($key, $default)
    if (is_int($value) || is_null($value)) {
        return $value;
    }
    throw $this->getException("int|null", $value);
}

protected function getString(string $key, string $default = ""): string
{
    if (is_string($value = $this->get($key, $default))) {
        return $value;
    }
    throw $this->getException("string", $value);
}

protected function getStringOrNull(string $key, string $default = ""): ?string
{
    $value = $this->get($key, $default)
    if (is_string($value) || is_null($value)) {
        return $value;
    }
    throw $this->getException("string|null", $value);
}

/** @param mixed $value */
private function getException(string $expected, $value): TypeException
{
    return new TypeException("expected parameter of type $expected but found " . gettype($value));
}

If the Symfony developers think this is a good idea and/or community members want it, I can work on a PR. I just didn't want to do the work only to find that this discussion has already been had, or there's something I'm missing, or such a feature wouldn't be accepted by Symfony.

And perhaps this logic shouldn't live in ParameterBag. Maybe it warrants a new Typer object that can be recycled all over the place. I currently have this type of logic implemented on a Trait that I include as needed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions