Доступ к Doctrine в пользовательском сервисе в Symfony4

Зная, что в сети есть много информации об этом, у меня все еще много проблем с тем, чтобы заставить это работать.

Я создал пользовательский сервис:

<?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 в конструктор! Любая помощь очень ценится

Можете ли вы опубликовать код с помощью службы (например, BookController)? Похоже, вы пытаетесь создать его самостоятельно?

ccKep 24.02.2019 23:49

Также: $this->em->getDoctrine()->getRepository(...) не будет работать, у EntityManager нет метода с именем getDoctrine. Наверное так и должно быть $this->em->getRepository(...)

ccKep 24.02.2019 23:51

попробуйте ввести DoctrineManager вместо интерфейса

AythaNzt 25.02.2019 01:13
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
0
3
1 347
4

Ответы 4

Вы используете неправильный сервис для того, что вы хотите сделать. Псевдоним 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(...) или использовать $this->em->getRepository(...) напрямую.

В 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)
    {
        ...
    }
}

Сказав это, я думаю, вам не нужен специальный сервис для выполнения простых операций с базой данных. Вместо этого используйте репозиторий.

Проблема в вашем 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');
        // ...
    }
}

В настоящее время сервисы можно внедрять в контроллеры с помощью автопроводка, что намного проще:

use Doctrine\ORM\EntityManagerInterface;

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

В Symfony 4 вам не нужно создавать его как сервис. Теперь это автоматически. Просто введите зависимости, которые вам нужны, в конструктор. Убедитесь, что у вас есть свойство autowire с истинным значением в services.yml (по умолчанию)

Удалите это из 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;
        }

    }
}

Другие вопросы по теме