Multiple services of type Doctrine\ORM\EntityManagerInterface found

Seifeak
Člen | 6
+
0
-

Zdravím, už po několikátý, když chci injectnout EntityManager z Doctrine, tak mi to háže tuto chybu:

Service ‚nettrine.migrations.nettrineDependencyFactory‘ (type of Nettrine\Migrations\DI\DependencyFactory): Multiple services of type Doctrine\ORM\EntityManagerInterface found: 03, doctrine.orm.entityManagerDecorator. If you want to overwrite service doctrine.orm.entityManagerDecorator, give it proper name. (required by $entityManager in DependencyFactory::__construct())

Snažím se udělat Registraci uživatele přes formulář, a následně uložit do databáze.
Tady mám RegisterPresenter:

<?php

namespace App\UI\Register;

use App\Model\Repository\UserRepository;
use Nette\Application\UI\Form;
use Nette\Application\UI\Presenter;
use Nette\ComponentModel\IComponent;
use Nette\DI\Attributes\Inject;
use Nette\Utils\ArrayHash;

class RegisterPresenter extends Presenter
{
    public $repository;
    public function __construct(UserRepository $repository)
    {
        $this->repository = $repository;
    }

    public function renderRegister()
    {

    }

    protected function createComponentRegistrationForm(): IComponent
    {
        $form = new Form();
        $form->addText("username", "Uživatelské jméno");
        $form->addEmail("email", "E-mailová adresa");
        $form->addPassword("password", "Heslo");
        $form->addSubmit("send", "Registrovat");
        $form->onSuccess[] = [$this, "formRegisterSucceeded"];
        return $form;
    }

    public function formRegisterSucceeded(Form $form, $data)
    {
        bdump($data);
        $this->repository->createUser($data);
        $this->flashMessage('Byl jste úspěšně zaregistrován.');
        $this->redirect('Home:');
    }
}

A tady UserRepository, který Presenter používá:

<?php

namespace App\Model\Repository;

use App\Model\Database\User;
use Doctrine\ORM\EntityManager;
use Nette\Security\Passwords;
use Nette\Utils\ArrayHash;

class UserRepository
{
    private Passwords $passwords;
    private EntityManager $em;

    public function __construct(Passwords $passwords, EntityManager $em)
    {
        $this->passwords = $passwords;
        $this->em = $em;
    }

    public function createUser(ArrayHash $data)
    {
        $userEntity = new User();
        $userEntity->setName($data["username"]);
        $userEntity->setEmail($data["email"]);
        $userEntity->setPassword($this->passwords->hash($data["password"]));
        $this->em->persist($userEntity);
        $this->em->flush();
    }
}

Zde je services.neon, kde po vložení – Doctrine\ORM\EntityManager to háže zmíněnou chybu.

services:
	- App\Core\RouterFactory::createRouter
	- App\Model\Repository\UserRepository
	- Doctrine\ORM\EntityManager


search:
    - in: %appDir%
      classes:
          - *Factory
          - *Facade

Když jsem zkusil EntityManager do UserRepository vložit přes atribut #[Inject], tak už to zprvu chybu nehodilo, ale zase po vyplnění formuláře, kdy se to snažilo uložit data do db, tak to hodilo tuto chybu na řádku u funkce em->persist(): ‚Typed property App\Model\Repository\UserRepository::$em must not be accessed before initialization‘

Co dělám špatně?

Editoval Seifeak (27. 6. 15:17)

nightfish
Člen | 509
+
0
-

Seifeak napsal(a):
Service ‚nettrine.migrations.nettrineDependencyFactory‘ (type of Nettrine\Migrations\DI\DependencyFactory): Multiple services of type Doctrine\ORM\EntityManagerInterface found: 03, doctrine.orm.entityManagerDecorator. If you want to overwrite service doctrine.orm.entityManagerDecorator, give it proper name. (required by $entityManager in DependencyFactory::__construct())

V textu chybové hlášky jsem zvýraznil tu pasáž, která ti říká, co máš udělat. Pro případ, že bys nevěděl, jak vytvořit v konfiguraci DI kontejneru pojmenovanou službu, přikládám odkaz na relevantní část dokumentace.

Seifeak
Člen | 6
+
+2
-

nightfish napsal(a):

Seifeak napsal(a):
Service ‚nettrine.migrations.nettrineDependencyFactory‘ (type of Nettrine\Migrations\DI\DependencyFactory): Multiple services of type Doctrine\ORM\EntityManagerInterface found: 03, doctrine.orm.entityManagerDecorator. If you want to overwrite service doctrine.orm.entityManagerDecorator, give it proper name. (required by $entityManager in DependencyFactory::__construct())

V textu chybové hlášky jsem zvýraznil tu pasáž, která ti říká, co máš udělat. Pro případ, že bys nevěděl, jak vytvořit v konfiguraci DI kontejneru pojmenovanou službu, přikládám odkaz na relevantní část dokumentace.

Díky, nevěděl jsem kde hledat. Omlouvám se za obtíž, mohlo mi to dojít samotnému. Pro příště už vím.

Opravil jsem to tím, že jsem :

- Doctrine\ORM\EntityManager

přepsal na

doctrine.orm.entityManagerDecorator: Doctrine\ORM\EntityManager

Editoval Seifeak (27. 6. 18:16)

MajklNajt
Člen | 489
+
+2
-

Treba to vôbec registrovať v services? Ja si injectujem vždy EntityManagerInterface…

Marek Bartoš
Nette Blogger | 1249
+
+3
-

Ta služba už je registrovaná skrze extension.

Pokud vyžaduješ EntityManager a ne EntityManagerInterface a nefunguje ti autowiring (automatické předání do služeb, které ten manager vyžadují), tak je to proto, že služba má autowiring povolený jen pro interface a proti tomu interface máš taky programovat.

Pokud nemáš dobrý důvod výchozí implementaci přetížit (máš case, který je třeba vyřešit děděním) nebo ji nechceš vyměnit za úplně jinou (to v tomhle případě neděláš, EntityManager je výchozí implementace pro EntityManagerInterface), tak ji nepřetěžuj

A když už přetěžuješ službu, tak pozor na to, že zápis doctrine.orm.entityManagerDecorator: Doctrine\ORM\EntityManager ti ji přetíží kompletně – konstruktor, autowiring i settery. Můžeš tak rozbít něco, co extension do služby nastavuje.

Pro přetížení služby je lepší konfiguraci rozepsat – klíč create (a případně arguments) jsou pro přetížení konstruktoru. Viz https://doc.nette.org/…ion/services#…

Klíč autowired určuje podle jakého typu funguje autowiring, viz https://doc.nette.org/…n/autowiring

V tvém případě bys vůbec neměl potřebovat službu v neonu definovat/upravovat

Editoval Marek Bartoš (28. 6. 10:09)

Seifeak
Člen | 6
+
0
-

Díky za rady, chtěl jsem použít EntityManagerInterface..