-1

I know how to generate an URL for a route. However now I need to generate an URL for a controller or for a controller with a method. I checked the sourced of UrlGenerator but did not find any relevant information. No information in Symfony docs as well.

The method of the controller has an associate url. This url will be used in controller but I need the generator to be a service.

FreeLightman
  • 2,224
  • 2
  • 27
  • 42
  • The method of the controller have an associate url? Or is not exposed via HTTP? Who need to use this url? Could be good an internal forward? – Matteo Dec 23 '19 at 11:38
  • @Matteo I updated the question. But I do not understand this "Could be good an internal forward?" – FreeLightman Dec 23 '19 at 11:46
  • Are you trying to [forward a request to another controller](https://symfony.com/doc/current/controller/forwarding.html)? – Cerad Dec 23 '19 at 12:48
  • @Cerad I do not need to make a request. I just need to generate an url. – FreeLightman Dec 23 '19 at 12:49
  • You want to generate a url with the controller:method as an argument? That is probably not going to work. Pretty sure you need to use the previously defined route name. – Cerad Dec 23 '19 at 12:51
  • 1
    You should provide some additional information to clarify your question such as how the controller and route (annotation or yaml or whatever) looks like – Frank B Dec 23 '19 at 17:14
  • @FrankB I am looking the solution which will work for every case not depending on controller or route. – FreeLightman Dec 23 '19 at 20:30
  • 1
    The point is that your question looks a bit strange to us. So all i want is to understand your problem but if you don't want to update your question then it is also fine to me ;-) – Frank B Dec 23 '19 at 20:33
  • 1
    The problem is, controller do not have "routes". Or may even have more than one route pointing to them. A controller class may have multiple public methods exposed with different routes, with no clear 1-to-1 relationship. So at most you would have to search the loaded route collection to see if any configured route have that class::method() in its "defaults". – yivi Dec 24 '19 at 17:57
  • @yivi Quite appropriate notice. I already considered to use route collection for this task. I think I found the solution for it. Just not ready to post it, need to prepare it. – FreeLightman Dec 24 '19 at 19:12

2 Answers2

0

Basically you need to:

1. Add a route to the controller

<?php

declare(strict_types=1);

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

final class BlogController extends AbstractController
{
    /**
     * @Route(path="blog", name="blog")
     */
    public function __invoke(): Response
    {
        return $this->render('blog/blog.twig');
    }
}

2. Generate url route for a route

See Symfony docs

use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class SomeService
{
    /**
     * @var UrlGeneratorInterface
     */
    private $urlGenerator;

    public function __construct(UrlGeneratorInterface $urlGenerator)
    {
        $this->urlGenerator = $urlGenerator;
    }

    public function go()
    {
        // ...

        // generate a URL with no route arguments
        $signUpPage = $this->urlGenerator->generateUrl('sign_up');

        // generate a URL with route arguments
        $userProfilePage = $this->urlGenerator->generateUrl('user_profile', [
            'username' => $user->getUsername(),
        ]);


        // generated URLs are "absolute paths" by default. Pass a third optional
        // argument to generate different URLs (e.g. an "absolute URL")
        $signUpPage = $this->urlGenerator->generateUrl('sign_up', [], UrlGeneratorInterface::ABSOLUTE_URL);

        // when a route is localized, Symfony uses by default the current request locale
        // pass a different '_locale' value if you want to set the locale explicitly
        $signUpPageInDutch = $this->urlGenerator->generateUrl('sign_up', ['_locale' => 'nl']);
    }
}
Tomas Votruba
  • 23,240
  • 9
  • 79
  • 115
  • Thanks for you suggestion but I do not see how it can help me.You just use `UrlGenerator`. I need something like this: `$generator->controllerUrl(\App\MyController::class, 'methodWithRoute')`. – FreeLightman Jan 03 '20 at 20:10
  • I understood the question. That's not possible. You need to use route name to do it – Tomas Votruba Jan 03 '20 at 22:11
0

So, here is the service. At least an example of how it could implemented. SF4

namespace App\Route;

use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RouterInterface;

class UrlGenerator
{
    /**
     * @var RouteCollection
     */
    private $collection;

    public function __construct(RouterInterface $router)
    {
        $this->collection = $router->getRouteCollection();
    }

    public function generate(string $controllerClass, string $method): string
    {
        foreach ($this->collection as $item) {
            $defaults = $item->getDefaults();
            $controllerPath = $defaults['_controller'];
            $parts = explode('::', $controllerPath);

            if ($parts[0] !== $controllerClass) {
                continue;
            }

            if ($parts[1] !== $method) {
                continue;
            }

            return $item->getPath();
        }

        throw new \RuntimeException(
            'Route for such combination of controller and method is absent'
        );
    }
}

Poorly tested but working solution.

FreeLightman
  • 2,224
  • 2
  • 27
  • 42