Multiple services of type Doctrine\ORM\EntityManagerInterface found
- Seifeak
- Člen | 6
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 | 518
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
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)
- Marek Bartoš
- Nette Blogger | 1275
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)