如何在Symfony应用程序中把CRUD操作分解成专门的服务类

118 阅读1分钟

这种方法的全部目的是将逻辑保持在一个尽可能小的类中。这将使我们更容易维护和重构代码,因为类会更小,并帮助我们避免创建一个 "上帝对象"。从技术上讲,一个类将做一件事。

结构

src/
├── Controller
│   └── CountryController.php
├── Entity
│   └── Country.php
├── Repository
│   ├── AbstractRepository.php
│   └── Country
│       └── Repository.php
└── Service
    └── Country
        ├── Create.php
        ├── Delete.php
        ├── Read.php
        └── Update.php

文件

国家控制器(CountryController

declare(strict_types=1);

namespace App\Controller;

use App\Service\Country\Read;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\JsonResponse;

/**
 * @Route("/countries")
 */
class CountryController
{
    private $read;

    public function __construct(
        Read $read
    ) {
        $this->read = $read;
    }

    /**
     * @Route("/{id}", methods="GET")
     */
    public function getOne(int $id): JsonResponse
    {
        $result = $this->read->one($id);

        return new JsonResponse($result);
    }

    /**
     * @Route("", methods="GET")
     */
    public function getAll(): JsonResponse
    {
        $result = $this->read->all();

        return new JsonResponse($result);
    }
    
    // Create, Update and Delete endpoints go here
}

创建

declare(strict_types=1);

namespace App\Service\Country;

use App\Repository\Country\Repository;

final class Create
{
    private $repository;

    public function __construct(Repository $repository)
    {
        $this->repository = $repository;
    }

    public function one(int $name): void
    {
    }

    public function batch(iterable $data): void
    {
    }
}

读取

declare(strict_types=1);

namespace App\Service\Country;

use App\Repository\Country\Repository;

final class Read
{
    private $repository;

    public function __construct(Repository $repository)
    {
        $this->repository = $repository;
    }

    public function one(int $id): iterable
    {
        return $this->repository->findOneById($id);
    }

    public function all(): iterable
    {
        return $this->repository->findAll();
    }
}

更新

declare(strict_types=1);

namespace App\Service\Country;

use App\Repository\Country\Repository;

final class Update
{
    private $repository;

    public function __construct(Repository $repository)
    {
        $this->repository = $repository;
    }

    public function one(int $name): void
    {
    }

    public function batch(iterable $data): void
    {
    }
}

删除

declare(strict_types=1);

namespace App\Service\Country;

use App\Repository\Country\Repository;

final class Delete
{
    private $repository;

    public function __construct(Repository $repository)
    {
        $this->repository = $repository;
    }

    public function one(int $name): void
    {
    }
}

摘要存储库(AbstractRepository

declare(strict_types=1);

namespace App\Repository;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;

abstract class AbstractRepository
{
    private $entityManager;
    private $entityName;

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

    protected function getEntityManager(): EntityManagerInterface
    {
        return $this->entityManager;
    }

    protected function getRepository(): EntityRepository
    {
        return $this->entityManager->getRepository($this->entityName);
    }
}

存储库

declare(strict_types=1);

namespace App\Repository\Country;

use App\Entity\Country;
use App\Repository\AbstractRepository;
use Doctrine\ORM\EntityManagerInterface;

class Repository extends AbstractRepository
{
    public function __construct(EntityManagerInterface $entityManager)
    {
        parent::__construct($entityManager, Country::class);
    }

    public function findAll(): iterable
    {
        return $this
            ->getRepository()
            ->createQueryBuilder('c')
            ->getQuery()
            ->getArrayResult();
    }

    public function findOneById(int $id): iterable
    {
        return $this
            ->getRepository()
            ->createQueryBuilder('c')
            ->where('c.id = :id')
            ->setParameter('id', $id)
            ->getQuery()
            ->getArrayResult();
    }
}