在 Symfony 中配置 HTTP 请求方法?

Configuring HTTP Request Methods in Symfony?

我正在尝试为一个项目进入 Symfony,但我(有点)无法弄清楚 Symfony 的工作原理。我之前在 Java Spring Boot 中做过几次这些事情,但是这个项目需要我在 PHP 中做这些事情,我也想学习。

我基本上所做的是创建一个实体、存储库和服务,现在我正在处理控制器。

我使用 make:entity(或 make:controller)

创建了实体、repo 和控制器

该服务应该包装存储库并进一步抽象事物。

我的问题:

  1. 在控制器中我有一个构造函数。那个真的叫吗?我需要它来初始化它在

    中使用的服务
  2. 如何定义需要使用的 HTTP 请求方法?我知道如何指定路由,但我如何定义它是否作为 GET、POST、PUT、DELETE 访问?关于控制器的 Symfony 文档没有指定这一点。

  3. 我稍后必须找出这个,所以我想我会在这里问:如果我想通过 api 持久化一个项目,我只是将对象作为 [=51] =]? (例如,如果我正在用邮递员进行测试)

这是我的实体:

?php
 
namespace App\Entity;
 
use App\Repository\FahrzeugRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
 
/**
 * @ORM\Entity(repositoryClass=FahrzeugRepository::class)
 */
class Fahrzeug
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;
 
    /**
     * @ORM\Column(type="string", length=255)
     */
    private $fahrgestellnummer;
 
    /**
     * @ORM\Column(type="integer", nullable=true)
     */
    private $tueren;
 
    /**
     * @ORM\Column(type="string", length=255)
     */
    private $modellbezeichnung;
 
    /**
     * @ORM\ManyToMany(targetEntity=Person::class, mappedBy="faehrt")
     */
    private $gefahren_von;
 
    /**
     * @ORM\ManyToOne(targetEntity=Marke::class, inversedBy="produziert")
     * @ORM\JoinColumn(nullable=false)
     */
    private $stammt_von;
 
    public function __construct()
    {
    $this->gefahren_von = new ArrayCollection();
    }
 
    public function getId(): ?int
    {
    return $this->id;
    }
 
    public function getFahrgestellnummer(): ?string
    {
    return $this->fahrgestellnummer;
    }
 
    public function setFahrgestellnummer(string $fahrgestellnummer): self
    {
    $this->fahrgestellnummer = $fahrgestellnummer;
 
    return $this;
    }
 
    public function getTueren(): ?int
    {
    return $this->tueren;
    }
 
    public function setTueren(?int $tueren): self
    {
    $this->tueren = $tueren;
 
    return $this;
    }
 
    public function getModellbezeichnung(): ?string
    {
    return $this->modellbezeichnung;
    }
 
    public function setModellbezeichnung(string $modellbezeichnung): self
    {
    $this->modellbezeichnung = $modellbezeichnung;
 
    return $this;
    }
 
    /**
     * @return Collection|Person[]
     */
    public function getGefahrenVon(): Collection
    {
    return $this->gefahren_von;
    }
 
    public function addGefahrenVon(Person $gefahrenVon): self
    {
    if (!$this->gefahren_von->contains($gefahrenVon)) {
        $this->gefahren_von[] = $gefahrenVon;
        $gefahrenVon->addFaehrt($this);
    }
 
    return $this;
    }
 
    public function removeGefahrenVon(Person $gefahrenVon): self
    {
    if ($this->gefahren_von->removeElement($gefahrenVon)) {
        $gefahrenVon->removeFaehrt($this);
    }
 
    return $this;
    }
 
    public function getStammtVon(): ?Marke
    {
    return $this->stammt_von;
    }
 
    public function setStammtVon(?Marke $stammt_von): self
    {
    $this->stammt_von = $stammt_von;
 
    return $this;
    }
}

我的回购:

<?php

namespace App\Repository;

use App\Entity\Fahrzeug;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

/**
 * @method Fahrzeug|null find($id, $lockMode = null, $lockVersion = null)
 * @method Fahrzeug|null findOneBy(array $criteria, array $orderBy = null)
 * @method Fahrzeug[]    findAll()
 * @method Fahrzeug[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class FahrzeugRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
    parent::__construct($registry, Fahrzeug::class);
    }

    // /**
    //  * @return Fahrzeug[] Returns an array of Fahrzeug objects
    //  */
    /*
    public function findByExampleField($value)
    {
    return $this->createQueryBuilder('f')
        ->andWhere('f.exampleField = :val')
        ->setParameter('val', $value)
        ->orderBy('f.id', 'ASC')
        ->setMaxResults(10)
        ->getQuery()
        ->getResult()
    ;
    }
    */

    /*
    public function findOneBySomeField($value): ?Fahrzeug
    {
    return $this->createQueryBuilder('f')
        ->andWhere('f.exampleField = :val')
        ->setParameter('val', $value)
        ->getQuery()
        ->getOneOrNullResult()
    ;
    }
    */
}
    

我的服务

<?php

namespace App\Service;

use App\Entity\Fahrzeug;
use App\Repository\FahrzeugRepository;
use Doctrine\ORM\EntityManagerInterface;

class FahrzeugService {

    private FahrzeugRepository $fahrzeugRepository;

    public function __construct() {
    $this->injectRepository();
    }

    private function injectRepository() {
    $this->fahrzeugRepository = $this->getDoctrine()->getManager()->getRepository(Fahrzeug::class);
    }

    public function findById(int $id): Fahrzeug {
    return $this->fahrzeugRepository->find($id);
    }

    //Returns an array
    public function findAll(): array
    {
    return $this->fahrzeugRepository->findAll();
    }

    public function save(Fahrzeug $fahrzeug): Fahrzeug {
    $this->fahrzeugRepository->persist($fahrzeug);

    //TODO: gucken ob persist reicht oder ob man eine neue instanz erzeugen muss

    $this->fahrzeugRepository->flush();
    return $fahrzeug;
    }

    //TODO UPdate - kann man das auch mittels save machen?

    
    public function delete(Fahrzeug $fahrzeug): Fahrzeug {

    /*TODO: Herausfinden was auf der anderen Seite passiert
    Idealerweise wird auf der anderen Seite das Feld genullt
    */

    $this->fahrzeugRepository->remove($fahrzeug);
    $this->fahrzeugRepository->flush();
    return $fahrzeug;
    }
}

我正在使用的控制器:

<?php

namespace App\Controller;

use App\Entity\Fahrzeug;
use App\Service\FahrzeugService;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class FahrzeugController extends AbstractController
{
    
    private FahrzeugService $fahrzeugService;

    //TODO wird der Controller initialisiert?
    public function __construct() {
    $this->fahrzeugService = new FahrzeugService();
    }

    #[Route('/fahrzeugIndex', name: 'fahrzeug')]
    public function index(): Response
    {
    return $this->render('fahrzeug/index.html.twig', [
        'controller_name' => 'FahrzeugController',
    ]);
    }

    #[Route('/fahrzeug/{id}', name: 'fahrzeug')]
    public function findById(int $id): Fahrzeug {
    return $this->fahrzeugService->findById($id);
    }

    #[Route('/fahrzeug', name: 'fahrzeug')]
    public function findAll(): array {
    return $this->fahrzeugService->findAll();
    }

    #[Route('/fahrzeugIndex', name: 'fahrzeug')]
    public function save(Fahrzeug $fahrzeug): Fahrzeug {
    return $this->fahrzeugService->save($fahrzeug);
    }

    public function delete(Fahrzeug $fahrzeug): Fahrzeug {
    return $this->fahrzeugService->delete($fahrzeug);
    }
}

PHP/Symfony 中的依赖注入与 Java/Spring 中的不同。如果要注入依赖项,则必须将其添加到构造函数中。该依赖项将使用 symfony 中内置的依赖项注入容器自动构建。

private FahrzeugService $fahrzeugService;
public function __construct(FahrzeugService $fahrzeugService)
{
   $this->fahrzeugService = $fahrzeugService;
}

您不必指定注入服务的方法。可以更改 class (Controller/Service/etc.) 的创建方式,但此处并非如此。

完成后,您可以使用

FahrzeugService 中调用方法
$this->fahrzeugService->[method]()

所以在你的情况下,你可以使用:

<?php

namespace App\Service;

use App\Entity\Fahrzeug;
use App\Repository\FahrzeugRepository;

class FahrzeugService {

    private FahrzeugRepository $fahrzeugRepository;

    public function __construct(FahrzeugRepository $fahrzeugRepository) {
       $this->fahrzeugRepository = $fahrzeugRepository;
    }

    //...
}

您不必从 EntityManager 获取存储库。这是可能的,但你不必这样做。

对于您的 HTTP 方法。您可以在注释中指定方法。由于您已经在使用新的注释,因此您可以使用

#[Route('/fahrzeugIndex', name: 'fahrzeug', methods:['GET', 'POST'])]