Repository: symfony/symfony
File: src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php (PHP)

Code before:
 * @author Iltar van der Berg <kjarli@gmail.com>
 */
final class RequestAttributeValueResolver implements ValueResolverInterface
{
    public function resolve(Request $request, ArgumentMetadata $argument): array
    {
        if ($argument->isVariadic()) {
            return [];
        }

        $name = $argument->getName();
        if (!$request->attributes->has($name)) {
            return [];
        }

        $value = $request->attributes->get($name);
        $type = $argument->getType();

        // Skip when no type declaration or complex types; fall back to other resolvers/defaults
        if (null === $type || str_contains($type, '|') || str_contains($type, '&')) {
            return [$value];
        }

        if ($value instanceof \Stringable) {
            $value = (string) $value;
        }

        if ('string' === $type) {
            if (null === $value) {
                if ($argument->isNullable()) {
                    return [null];
                }

                throw new NotFoundHttpException(\sprintf('The value for the "%s" route parameter is invalid.', $name));
            }

            if (\is_scalar($value)) {
                return [(string) $value];
            }

            throw new NotFoundHttpException(\sprintf('The value for the "%s" route parameter is invalid.', $name));
        }

        if ($filter = match ($type) {
            'int' => \FILTER_VALIDATE_INT,
            'float' => \FILTER_VALIDATE_FLOAT,
            'bool' => \FILTER_VALIDATE_BOOL,
            default => null,
        }) {
            $filtered = $request->attributes->filter($name, null, $filter, [
                'flags' => \FILTER_NULL_ON_FAILURE | \FILTER_REQUIRE_SCALAR,

Review comment (suggestion):
This doesn't seem to work as expected. I'm seeing this error:

> Symfony\Component\HttpKernel\Controller\ErrorController::__invoke(): Argument #1 ($exception) must be of type Throwable, string given.

Because `Throwable` implements `__toString()`, the exception ends up being cast to a string. That conversion should only happen when the controller argument is actually typed as `string`, not `Throwable`.

Code after:
 * @author Iltar van der Berg <kjarli@gmail.com>
 */
final class RequestAttributeValueResolver implements ValueResolverInterface
{
    public function resolve(Request $request, ArgumentMetadata $argument): array
    {
        if ($argument->isVariadic()) {
            return [];
        }

        $name = $argument->getName();
        if (!$request->attributes->has($name)) {
            return [];
        }

        $value = $request->attributes->get($name);

        if (null === $value && $argument->isNullable()) {
            return [null];
        }

        $type = $argument->getType();

        // Skip when no type declaration or complex types; fall back to other resolvers/defaults
        if (null === $type || str_contains($type, '|') || str_contains($type, '&')) {
            return [$value];
        }

        if ('string' === $type) {
            if (!\is_scalar($value) && !$value instanceof \Stringable) {
                throw new NotFoundHttpException(\sprintf('The value for the "%s" route parameter is invalid.', $name));
            }

            $value = (string) $value;
        } elseif ($filter = match ($type) {
            'int' => \FILTER_VALIDATE_INT,
            'float' => \FILTER_VALIDATE_FLOAT,
            'bool' => \FILTER_VALIDATE_BOOL,
            default => null,
        }) {
            if (null === $value = $request->attributes->filter($name, null, $filter, ['flags' => \FILTER_NULL_ON_FAILURE | \FILTER_REQUIRE_SCALAR])) {
                throw new NotFoundHttpException(\sprintf('The value for the "%s" route parameter is invalid.', $name));
            }
        }

        return [$value];
    }
}