Generate a link from a service

2019-04-18 01:56发布

问题:

How can I generate a link from a service? I've injected "router" inside my service, however generated links are /view/42 instead of /app_dev.php/view/42. How can I solve this?

My code is something like this:

services.yml

services:
    myservice:
        class: My\MyBundle\MyService
        arguments: [ @router ]

MyService.php

<?php

namespace My\MyBundle;

class MyService {

    public function __construct($router) {

        // of course, the die is an example
        die($router->generate('BackoffUserBundle.Profile.edit'));
    }
}

回答1:

So : you will need two things.

First of all, you will have to have a dependency on @router (to get generate()).

Secondly, you must set the scope of your service to "request" (I've missed that). http://symfony.com/doc/current/cookbook/service_container/scopes.html

Your services.yml becomes:

services:
    myservice:
        class: My\MyBundle\MyService
        arguments: [ @router ]
        scope: request

Now you can use the @router service's generator function !


Important note regarding Symfony 3.x: As the doc says,

The "container scopes" concept explained in this article has been deprecated in Symfony 2.8 and it will be removed in Symfony 3.0.

Use the request_stack service (introduced in Symfony 2.4) instead of the request service/scope and use the shared setting (introduced in Symfony 2.8) instead of the prototype scope (read more about shared services).



回答2:

I had a similar issue, but using Symfony 3. While eluded to in the previous answer, it was a bit tricky to find out how exactly one would use request_stack to achieve the same thing as scope: request.

In this question's case, it would look something like this:

The services.yml config

services:
    myservice:
        class: My\MyBundle\MyService
        arguments:
            - '@request_stack'
            - '@router'

And the MyService Class

<?php

    namespace My\MyBundle;

    use Symfony\Component\Routing\RequestContext;

    class MyService {

        private $requestStack;
        private $router;

        public function __construct($requestStack, $router) {
            $this->requestStack = $requestStack;
            $this->router = $router;
        }

        public doThing() {
            $context = new RequestContext();
            $context->fromRequest($this->requestStack->getCurrentRequest());
            $this->router->setContext($context);
            // of course, the die is an example
            die($this->router->generate('BackoffUserBundle.Profile.edit'));
        }
    }

Note: Accessing RequestStack in the constructor is advised against since it could potentially try to access it before the request is handled by the kernel. So it may return null when trying to fetch the request object from RequestStack.