-1

as you know controllers in symfony extends AbstractController i want to add some usual methods in base controller and simply use in my method in controller like $this->validate for example so i created a BaseController that extends AbstractController . the issue is how can i use my ValidationService in BaseController? i have to add construct in BaseController and so again pass parent Constructor. another solution is get my ValidationService in BaseController like $this->container->get("my.validation.service") that gives me error like this :

Service "my.validation.service" not found: even though it exists in the app's container, the container inside "App\Controller\VendorController" is a smaller service locator that only knows about the "form.factory", "http_kernel", "parameter_bag", "request_stack", "router", "security.authorization_checker", "security.csrf.token_manager", "security.token_storage", "serializer" and "twig" services. Try using dependency injection instead.

what is the best practice for this?

sina
  • 226
  • 3
  • 11
  • Implement `ServiceSubscriberInterface`. See [`AbstractController`](https://github.com/symfony/symfony/blob/ddaedd28bd2e4fc22b64567753cf934fe9d68c4c/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php#L85) for an example. You can merge your container with that of `AbstractController`. BTW, there's no constructor in `AbstractController` so you may want to be more precise on detailing your environment and what your problem is exactly. – msg Aug 29 '22 at 19:37
  • @msg i have a validationService and i want to user in my all controllers and i dont want to inject it in all my controllers and use it simply like $this->getParameter() for example because its task i routine for all controllers mention that i dont know it is good practice or not – sina Aug 29 '22 at 19:43
  • Yes, perfectly valid. The [documentation](https://symfony.com/doc/current/controller.html#the-base-controller-class-services) states "To aid development, Symfony comes with an optional base controller class". You can use it, not use it or use your own. – msg Aug 29 '22 at 19:45
  • @msg i know for my purpose what is you suggestion that doesn`t violate any principle and be the best practice? – sina Aug 29 '22 at 19:48
  • @msg any idea my friend? – sina Aug 29 '22 at 20:29
  • 2
    It's a matter of opinion at this point. If you are just starting, inheriting from `AbstractController` and injecting other services will get you an starting point without having to replicate already existing code. Others might say you should write a completely custom controller with exactly what you need. You have to ask yourself: Do I plan on switching frameworks? If the answer is no, extending `AbstractController` will be fine. – msg Aug 29 '22 at 20:55
  • Not sure if it will help or not but [here is an example](https://stackoverflow.com/questions/60078704/adding-services-to-a-controller-through-container-service-subscriber-not-worki/60079875#60079875) of using getSubscribedServices() to add a service to AbstractController. Using it is fine from Symfony's point of view however, in my own humble experience, it's rare to come across functionality that all controllers really need. An alternate approach might be to move your validation code to a trait and just add it to a controller as needed. – Cerad Aug 30 '22 at 12:37

1 Answers1

1

It sounds like you should be using constructor injection and standard PHP inheritance here (this uses property promotion from php 8)


namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use App\Service\ValidationService;

class MyCustomBaseController extends AbstractController
{
    public function __construct(private readonly ValidationService $validationService)
    {
    }
}
namespace App\Controller;

use App\Controller\MyCustomBaseController;

class MyNormalController extends MyCustomBaseController
{
    public function foo()
    {
        $this->validationService->foo();
    }
}
craigh
  • 1,909
  • 1
  • 11
  • 24