Symfony 4, How to implement a general controller as a service?

匆匆过客 提交于 2019-12-01 11:14:38

It looks like your import of the service is wrong and some other things that we spoke about in tchat.

Important :

  • The service should be in src/Servicefolder.
  • The service should not be excluded in services.yml

Final solution for people :

The service :

namespace App\Service;

use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Doctrine\ORM\EntityManagerInterface; 

class GeneralService
{

    private $entityManager;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->entityManager = $entityManager;
    } 

    /**
     * @param Request $request
     * @param String $entity
     * @return JsonResponse
     */
    public function list(Request $request, String $entity)
    {
        if (empty($request->headers->get('api-key'))) {
            return new JsonResponse(['error' => 'Please provide an API_key'], 401);
        }

        if ($request->headers->get('api-key') !== $_ENV['API_KEY']) {
            return new JsonResponse(['error' => 'Invalid API key'], 401);
        }

        return new JsonResponse($this->entityManager->getRepository($entity)->findAll()); 
    }

}

And the controller :

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use App\Service\GeneralService;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;

class SubscriptionController extends AbstractController
{

    /**
    * @Route("/Some/Uri", methods={"GET"})
    * @param GeneralService $generalService
    * @param Request $request
    * @return JsonResponse
    */
    public function AuthenticateAPI(GeneralService $generalService, Request $request)
    {
        $AuthenticatorObject = $generalService->list($request , 'App\Entity\Something');
        return $AuthenticatorObject;
    }
}

Okay. Back to the basics. Start by getting yourself an IDE such a PHPStorm. It will highlight various syntax errors and what not. In particular, the IDE will help with the service namespace issue as well as assorted other problems.

The fundamental concept behind dependency injection is that dependencies needed by a given class should be, well, injected. Your GeneralService class needs the entity manager. In your previous identical question you had GeneralService extending AbstractController because AbstractController has a getDoctrine method. It still would not have have worked because getDoctrine in turn needs the service container. And of course in your current code, GeneralService has no getDoctrine method at all.

In any event, since GeneralService needs the entity manager then inject it:

# src/Service/GeneralService.php
namespace App\Service; # NOTE App\Service not just Service

use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

class GeneralService
{
    private $entityManager;

    // Let Symfony inject whatever dependencies are needed
    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->entityManager = $entityManager;
    }
    public function list(Request $request, String $entityClass) : JsonResponse
    {
        if (!$request->headers->has('api-key')) {
            return new JsonResponse(['error' => 'Please provide an API_key'], 401);
        }

        if (!$request->headers->get('api-key') !== $_ENV['API_KEY']) {
            return new JsonResponse(['error' => 'Invalid API key'], 401);
        }

        return new JsonResponse($this->entityManager->getRepository($entityClass)->findAll());
    }
}

And do not exclude the GeneralService anymore.

Your controller class is pretty much okay once you use an IDE to get rid of all the little syntax errors:

namespace App\Controller;

use App\Service\GeneralService;
use App\Entity\SomeEntity;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;

class SubscriptionClass extends AbstractController
{
    public function AuthenticateAPI(Request $request, GeneralService $generalService)
    {
        $AuthenticatorObject = $generalService->list($request,SomeEntity::class);
        return $AuthenticatorObject;
    }

}

I did not actually test the above code though it should get you at least one step further.

One final note: Don't access any of the super globals directly i.e. $_ENV['API_KEY'] is a no no. The api_key should be injected along with the entity manager. I'll leave the exact details as an exercise for the student since injecting strings is a little bit different from injecting objects.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!