-1

In this Symfony route

/**
 * @Route("/board/{board}/card/{card}", name="card_show", methods={"GET"}, options={})
 */
public function show(Board $board, Card $card): Response
{
    $card->getLane()->getBoard(); // Board instance
    // ...
}

How is it possible to add the {board} parameter programatically, since it is already available in {card}? Now, I always need to add two parameters, when generating links to show action.

After some research I've found the RoutingAutoBundle (https://symfony.com/doc/master/cmf/bundles/routing_auto/introduction.html#usage) which would provide the functions I need, but it's not available for Symfony 5 anymore.

Thanks.

8
  • 1
    why not change route to /card/{card} and be done with it? You also could just ignore the board parameter (remove it from function signature), if you retrieve board from card anyway ...... Commented Aug 16, 2020 at 21:36
  • Why not provide parameters in routes programmatically? I want to get rid of the required board parameter, but I also want to decorate the URI to display the structure. This is seo related. Commented Aug 17, 2020 at 9:50
  • 1
    There is a UrlGenerator(Interface) that's responsible for generating urls. If you're bend on generating stuff yourself, maybe you can extend that ... or you can hack the entire Router(Interface) Commented Aug 17, 2020 at 9:56
  • I don't get why some people vote this question down... Commented Aug 17, 2020 at 14:19
  • it's all about expectations. here (php/symfony) the expectation usually is, that the question should show efforts in solving the problem, with code, maybe particular error messages, none of which applies to your question. Thus the question is perceived "lazy" and might even have been closed for various reasons like opinionated / looking for resources. But the line to be drawn is quite variable and I can understand where you're coming from. shrug Commented Aug 17, 2020 at 14:42

1 Answer 1

2

Okay, after some investigation I've found this question Which lead me to this helpful answer.

My controller action (with @Route annotation) looks like this:

/**
 * @Route("/board/{board}/card/{card}", name="card_show", methods={"GET"})
 */
public function show(Card $card): Response
{
}

We just have one argument ($card) in method signature, but two arguments in route.

This is how to call the route in twig:

path("card_show", {card: card.id})

No board parameter required, thanks to a custom router.

This is how the custom router looks like:

<?php // src/Routing/CustomCardRouter.php

namespace App\Routing;

use App\Repository\CardRepository;
use Symfony\Component\Routing\RouterInterface;

class CustomCardRouter implements RouterInterface
{
    private $router;
    private $cardRepository;

    public function __construct(RouterInterface $router, CardRepository $cardRepository)
    {
        $this->router = $router;
        $this->cardRepository = $cardRepository;
    }

    public function generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH)
    {
        if ($name === 'card_show') {
            $card = $this->cardRepository->findOneBy(['id' => $parameters['card']]);
            if ($card) {
                $parameters['board'] = $card->getLane()->getBoard()->getId();
            }
        }
        return $this->router->generate($name, $parameters, $referenceType);
    }

    public function setContext(\Symfony\Component\Routing\RequestContext $context)
    {
        $this->router->setContext($context);
    }

    public function getContext()
    {
        return $this->router->getContext();
    }

    public function getRouteCollection()
    {
        return $this->router->getRouteCollection();
    }

    public function match($pathinfo)
    {
        return $this->router->match($pathinfo);
    }
}

Now, the missing parameter board is provided programatically, by injecting and using the card repository. To enable the custom router, you need to register it in your services.yaml:

App\Routing\CustomCardRouter:
    decorates: 'router'
    arguments: ['@App\Routing\CustomCardRouter.inner']
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.