Hantsy
Hantsy

Reputation: 9261

How to read the reflection data on primitive type?

The original post: https://github.com/symfony/symfony/discussions/43960

I want to use a QueryParam attribute to read a query string into a Controller method argument.

An example controller class.

#[Route("/posts")]
class PostController extends AbstractController{
    //... other methods.

    #[Route(path: "", name: "all", methods: ["GET"])]
    function all(#[QueryParam] string $keyword,
                 #[QueryParam] int $offset = 0,
                 #[QueryParam] int $limit = 20): Response
    {
        $data = $this->posts->findByKeyword($keyword || '', $offset, $limit);
        return $this->json($data);
    }
}

Then I tried to create a QueryParam attribute and a custom ParamConverter to archive the purpose.

#[Attribute(Attribute::TARGET_PARAMETER)]
final class QueryParam
{
    private string $name;

    /**
     * @return string
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * @param string $name
     * @return QueryParam
     */
    public function setName(string $name): QueryParam
    {
        $this->name = $name;
        return $this;
    }
}

The source codes of QueryParamParamConverter.

class QueryParamParamConverter implements ParamConverterInterface, LoggerAwareInterface
{
    public function __construct()
    {
    }

    private LoggerInterface $logger;

    /**
     * @inheritDoc
     * @throws ReflectionException
     */
    public function apply(Request $request, ParamConverter $configuration): bool
    {
        $param = $configuration->getName();
        $this->logger->debug("configuration name: " . $param);
        $className = $configuration->getClass();
        $reflector = new ReflectionClass($className);
        $attrs = $reflector->getAttributes(QueryParam::class);
        $attr = $attrs[0];
        $name = $attr->getArguments()[0] ?? $param;
        $value = $request->attributes->get($param);
        $this->logger->debug("set request attribute name: " . $name . ", value: " . $value);
        $request->attributes->set($name, $value);
        return true;
    }

    /**
     * @inheritDoc
     * @throws ReflectionException
     */
    public function supports(ParamConverter $configuration): bool
    {
        $className = $configuration->getClass();
        $this->logger->debug("class name:" . $className);
        if ($className) {
            // determine this method argument is annotated with `QueryParam`?
        }

        return false;
    }

    public function setLogger(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
}

The $className = $configuration->getClass(); always return empty string instead of a class name.

I am not sure what is the best way to select a method argument with QueryParam.

Upvotes: 0

Views: 162

Answers (0)

Related Questions