在Symfony4中的自定义服务中访问主义

时间:2019-02-24 22:20:49

标签: symfony orm doctrine-orm doctrine symfony-4.2

意识到网络上有很多与此有关的信息,我仍然很难使它起作用。

我已经创建了一个自定义服务:

<?php

namespace App\Service;

use Doctrine\ORM\EntityManagerInterface;
use App\Entity\AccommodationType;
use App\Entity\Night;

class AvailabilityChecks {

    private $em;

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

    public function nightAvailable(string $RoomCode, string $NightDate) {


        $GetRoom = $this->em->getDoctrine()->getRepository(AccommodationType::class)->findOneBy([
                'RoomCode' => $RoomCode
            ]);

        $RoomQnt = $GetRoom->getNightlyQnt();

        $GetNight = $this->em->getDoctrine()->getRepository(Night::class)->findOneBy([
                'RoomCode' => $RoomCode,
                'NightDate' => $NightDate
            ]);

        $NumberOfNights = $GetNight->count();

        if($NumberOfNights<$RoomQnt) {
            return true;
        }
        else {
            return false;
        }

    }


}

并将其放在services.yaml中:

AvailabilityChecks.service:
  class: App\Service\AvailabilityChecks
  arguments: ['@doctrine.orm.entity_manager']

因此,当我尝试在控制器中使用它时,会出现此错误:

Too few arguments to function App\Service\AvailabilityChecks::__construct(), 0 passed in /mypath/src/Controller/BookController.php on line 40 and exactly 1 expected

我只是想不出为什么没有将ORM注入到构造函数中!任何帮助表示赞赏

4 个答案:

答案 0 :(得分:2)

问题出在您的BookController中。即使您没有发布其代码,我也可以假设您在其中创建了new AvailabilityChecks(第40行)。

在Symfony中,每个服务都由服务容器实例化。您永远不要自己使服务对象实例化。相反,BookController必须向服务容器请求AvailabilityChecks服务。应该怎么做?

在Symfony <3.3中,我们通常使用:

use Symfony\Bundle\FrameworkBundle\Controller\Controller;


class MyController extends Controller 
{
    public function myAction() 
    {
        $em = $this->get('doctrine.orm.entity_manager');
        // ...
    }
}

现在可以使用autowiring在控制器中注入如今的服务,这更容易:

use Doctrine\ORM\EntityManagerInterface;

class MyController extends Controller 
{
    public function myAction(EntityManagerInterface $em) 
    {
        // ...
    }
}

答案 1 :(得分:1)

您使用的服务不正确。使用的别名@model IEnumerable<ShimbaSchool.Models.Staff> @{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_MyLayout.cshtml"; } <h2>Index</h2> <p> @Html.ActionLink("Create New", "Create") </p> <table class="table"> <tr> <th> @Html.DisplayNameFor(model => model.ImagePath) </th> <th> @Html.DisplayNameFor(model => model.StaffName) </th> <th> @Html.DisplayNameFor(model => model.StaffSpecialty) </th> <th></th> </tr> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.ImagePath) </td> <td> @Html.DisplayFor(modelItem => item.StaffName) </td> <td> @Html.DisplayFor(modelItem => item.StaffSpecialty) </td> <td> @Html.ActionLink("Edit", "Edit", new { id=item.StaffId }) | @Html.ActionLink("Details", "Details", new { id=item.StaffId }) | @Html.ActionLink("Delete", "Delete", new { id=item.StaffId }) </td> </tr> } </table> ,例如调用doctrine时AbstractController中的绑定到服务getDoctrine()

因此,您编写的代码更适合于此,您应该在服务定义中添加Doctrine\Common\Persistence\ManagerRegistry@doctrine

使用当前配置或更改后的配置,您都不必调用@Doctrine\Common\Persistence\ManagerRegistry,因为$this->em->getDoctrine()已经等效于控制器中的$this->em。相反,您可以创建一个(私有)方法,使其看起来更像该代码,例如:

$this->getDoctrine()

然后,您可以致电private function getDoctrine() { return $this->em; } 或直接使用$this->getDoctrine()->getRepository(...)

答案 2 :(得分:1)

在SF4中,您不再需要在service.yaml文件中指定自定义服务所需的依赖项。您要做的就是使用依赖注入。

因此,删除配置行,然后直接在控制器方法中调用您的服务:

<?php

namespace App\Controller;

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

class AppController extends AbstractController
{
    public function index(AvailabilityChecks $service)
    {
        ...
    }
}

话虽如此,我认为您不需要自定义服务即可对数据库进行简单的操作。改用存储库。

答案 3 :(得分:1)

在Symfony 4中,您无需将其创建为服务。现在是自动的。只需在构造函数中注入所需的依赖项即可。确保您在services.yml中具有具有真值的autowire属性(默认情况下)

从services.yml中删除它:

AvailabilityChecks.service:
  class: App\Service\AvailabilityChecks
  arguments: ['@doctrine.orm.entity_manager']

您不需要EntityManagerInterface,因为您没有持久化任何东西,因此仅注入存储库。

<?php

namespace App\Service;

use App\Entity\AccommodationType;
use App\Entity\Night;
use App\Repository\AccommodationTypeRepository;
use App\Repository\NightRepository;

class AvailabilityChecks {

    private $accommodationTypeRepository;
    private $nightRepository

     public function __construct(
          AcommodationTypeRepository  $acommodationTypeRepository,
          NightRepository $nightRepository
    )
    {
        $this->acommodationTypeRepository = $acommodationTypeRepository;
        $this->nightRepository = $nightRepository;
    }

    public function nightAvailable(string $RoomCode, string $NightDate) {


        $GetRoom = $this->acommodationTypeRepository->findOneBy([
                'RoomCode' => $RoomCode
            ]);

        $RoomQnt = $GetRoom->getNightlyQnt();

        $GetNight = $this->nightRepository->findOneBy([
                'RoomCode' => $RoomCode,
                'NightDate' => $NightDate
            ]);

        $NumberOfNights = $GetNight->count();

        if($NumberOfNights<$RoomQnt) {
            return true;
        }
        else {
            return false;
        }

    }
}