Reputation: 1452
How can I inject a service (the service that I created) into my Controller? A setter injection would do.
<?php
namespace MyNamespace;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class MyController extends Controller
{
public function setMyService(MyService $myService)
{
$this->myService = $myService;
}
public function indexAction()
{
//Here I cannot access $this->myService;
//Because the setter is not called magically!
}
}
And my route settings :
// Resources/routing.yml
myController_index:
pattern: /test
defaults: { _controller: "FooBarBundle:MyController:index" }
I'm setting the service in another bundle :
// Resources/services.yml
parameters:
my.service.class: Path\To\My\Service
services:
my_service:
class: %my.service.class%
When the route is resolved, the service is not injected ( I know it shouldn't ). I suppose somewhere in a yml file, I have to set:
calls:
- [setMyService, [@my_service]]
I am not using this Controller as a service, it's a regular Controller that serves a Request.
Edit: At this point in time, I am getting the service with $this->container->get('my_service'); But I need to inject it.
Upvotes: 7
Views: 17621
Reputation: 14195
Since it's 2017 ending now and there is no tag for Symfony 3 or upcoming Symfony 4 (and I think there should not be), this problem is solvable in a native much better way.
If you are still struggling and somehow ended up on this page and not in Symfony docs, then you should know, that you do not need to declare controller as service, as it is already registered as one.
What you need to do, is check you services.yml
:
# app/config/services.yml
services:
# default configuration for services in *this* file
_defaults:
# ...
public: false
Change public: false
to public:true
if you want all services to be public.
Or explicitly add a service and declare it public:
# app/config/services.yml
services:
# ... same code as before
# explicitly configure the service
AppBundle\Service\MessageGenerator:
public: true
And then in your controller you can get the service:
use AppBundle\Service\MessageGenerator;
// accessing services like this only works if you extend Controller
class ProductController extends Controller
{
public function newAction()
{
// only works if your service is public
$messageGenerator = $this->get(MessageGenerator::class);
}
}
Read more:
Upvotes: 3
Reputation: 7586
When using the JMSDiExtraBundle you DON'T have to define your controller as a service (unlike @elnur said) and the code would be:
<?php
namespace MyNamespace;
use JMS\DiExtraBundle\Annotation as DI;
use Path\To\My\Service;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class MyController extends Controller
{
/**
* @var $myService Service
*
* @DI\Inject("my_service")
*/
protected $myService;
public function indexAction()
{
// $this->myService->method();
}
}
I find this approach very nice because you avoid writing a __construct()
method.
Upvotes: 6
Reputation: 291
If you don't want to define your controller as a service, you can add a listener to the kernel.controller event to configure it just before it is executed. This way, you can inject the services you need inside your controller using setters.
Upvotes: 0
Reputation: 44831
If you want to inject services into your controllers, you have to define controllers as services.
You could also take a look at JMSDiExtraBundle's special handling of controllers — if that solves your problem. But since I define my controllers as services, I haven't tried that.
Upvotes: 7