protected function bindParameters(callable $controller, array $matched): array
    {
        if (is_array($controller)) {
            $reflector = new \ReflectionMethod($controller[0], $controller[1]);
            $controllerName = sprintf('%s::%s()', get_class($controller[0]), $controller[1]);
        } elseif (is_object($controller) && ! $controller instanceof \Closure) {
            $reflector = (new \ReflectionObject($controller))->getMethod('__invoke');
            $controllerName = get_class($controller);
        } else {
            $controllerName = ($controller instanceof \Closure) ? get_class($controller) : $controller;
            $reflector = new \ReflectionFunction($controller);
        }

        $parameters = $reflector->getParameters();

        $bindParams = [];
        foreach ($parameters as $param) {
            // @notice \ReflectionType::getName() is not supported in PHP 7.0, that is why we use __toString()
            $paramType = $param->hasType() ? $param->getType()->__toString() : '';
            $paramClass = $param->getClass();

            if (array_key_exists($param->getName(), $matched)) {
                $bindParams[] = $this->transformToScalar($matched[$param->getName()], $paramType);
            } elseif ($paramClass && array_key_exists($paramClass->getName(), $matched)) {
                $bindParams[] = $matched[$paramClass->getName()];
            } elseif ($param->isDefaultValueAvailable()) {
                $bindParams[] = $param->getDefaultValue();
            //} elseif ($param->hasType() && $param->allowsNull()) {
            //    $result[] = null;
            } else {
                // can't find the value, or the default value for the parameter => throw an error
                throw new InvalidArgumentException(sprintf(
                    'Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value or because there is a non optional argument after this one).',
                    $controllerName,
                    $param->getName()
                ));
            }
        }

        return $bindParams;
    }