Továrna pro EntityManager

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Čejen
Člen | 4
+
0
-

1) Potřebuji vytvořit více instancí Doctrine EntityManageru. Proto jsem vyzkoušel nový koncept továrem Nette 2.1 pomocí definice rozhraní s metodou create. A ejhle co mi kontejner hlásí:

Class \Doctrine\ORM\EntityManager used in service ‚entityManagerFactory‘ has not been found or is not instantiable.

Tak se dám do ladění a zjistím, že výraz Reflection\ClassType::from("\Doctrine\ORM\EntityManager")->isInstantiable() v ContainerBuilderu se vyhodnotí jako false. Myslím, že to asi není chyba Nette, ale PHP. Nicméně nemám tucha, proč. Nesetkal jste se již někdo s touto chybou? Dovolím si požádat o odpověď bez spekulací, proč vlastně více instancí entity managera potřebuji (že je to chyba návrhu a podobně).

2) Doctrine EntityManager chápu jako jakoukoliv jinou službu a do Nette jsem si ji integroval čistě přes config.neon. Pokud si zaregistruji Doctrine pomocí extension (např. Nella), dokážu ze systémového kontejneru dostat právě jednu instanci EntityManageru. Je to pravda? Vznikne sice metoda createServiceXXX, ale tu nemám v ostatních službách dostupnou (ledaže by si předal celý kontejner). Nebo mi něco uniklo?

3) Rád bych řízení transakcí u servisních metod ovládal anotacemi (podobně jako ve Springu). Znamená to, že musím změnit způsob, jakým se generuje kód metod kontejneru createServiceXXX (abych mohl případně zakládanou službu dekorovat). Které řešení je podle Vás správné (nepotřebuji žádné další parametry v config.neon, vystačím si s reflexí):

  1. Formou Extension
  2. Napsáním vlastního kompileru

Mohl bych si sice takové servisy zakládat přes nějakou vlastní továrnu, ale tím bych se myslím musel vzdát autowiringu.

Předem moc děkuji za radu

Filip Procházka
Moderator | 4668
+
0
-

Potřebuji vytvořit více instancí Doctrine EntityManageru.

Takhle se to nedělá, použij kdyby/doctrine kde si budeš moct nakonfigurovat více EntityManagerů a pak si je předáš kam budeš potřebovat.

Myslím, že to asi není chyba Nette, ale PHP. Nicméně nemám tucha, proč.

Není to chyba, ale feature. EntityManager nemá jít vytvářet přes konstruktor, obsahuje tovární funkci create.

*Pokud si zaregistruji Doctrine pomocí extension (např. Nella), dokážu ze systémového kontejneru dostat právě jednu instanci EntityManageru. Je to pravda? Vznikne sice metoda createServiceXXX, ale tu nemám v ostatních službách dostupnou (ledaže by si předal celý kontejner). Nebo mi něco uniklo?

Když použiješ Kdyby/Doctrine

doctrine:
	default:
		user: foo
		password: nemam
		dbname: projekt

	extra:
		user: foo
		password: nemam
		dbname: projekt_extra

Vytvoří se tí několik EntityManagerů, kde default získáš vždy když si necháš injectnout Doctrine\ORM\EntityManager a pokud budeš chtít ten „extra“, tak si ho předáš na úrovni configu

services:
	nejakaSluzba: App\NejakyModel(
		@doctrine.default.entityManager,
		@doctrine.extra.entityManager
	)

Pokud ti stačí výchozí tak si vytvoříš třídu co vyžaduje EM a nebudeš ji configurovat

class Foo
{
	public function __construct(Doctrine\ORM\EntityManager $em)
	{

	}
}
services:
	# Výchozí je @doctrine.default.entityManager
	nejakaSluzba: Foo()

Tímto způsobem si můžeš předat jednotlivé EntityManagery do modelů kde s nimi potřebuješ pracovat a tyto modely pak použiješ v presenterech.

Čejen
Člen | 4
+
0
-

Díky za pomoc. Přiznám se, že koncept registrace Doctrine (ale i jiných frameworků) formou extensions se mi moc nelíbí, ale to je na jinou debatu. Každopádně teprve až po Tvé odpovědi jsem si všimnul, že třída \Doctrine\ORM\EntityManager nemá veřejný konstruktor. Tímto se omlouvám, za plýtvání Tvým časem.
Ještě doplňující otázka: vystačil bych si z kdyby/doctrine, pokud opravdu potřebuji továrnu na Entity Managery? Jejich počet není dopředu znám a jsou instancovány průběžně, podle potřebného počtu nezávislých transakcí. Jak bych tuto továrnu dostal do service? Děkuji za radu

Filip Procházka
Moderator | 4668
+
0
-

Kdyby/Doctrine toho sice umí o dost víc, ale i pokud ti jenom stačí, aby za tebe řešil konfiguraci, tak se rozhodně vyplatí použít.

A pokud se někdy stavíš na nettefw chat tak ti odpor obecně k extensions rozhodně rozmluvíme :)

Čejen
Člen | 4
+
0
-

Je dost možné, že jsem Extensions úplně nepochopil. S Nette začínám, tak se rozkoukávám. Nicméně bych ještě jednou požádal o radu: nabízí kdyby\doctrine nějakou továrnu, kterou mohu požádat o novou instanci Entity Managera s danou konfigurací (např. shodnou s default). Mě by stačila jedna konfigurace, ale více instancí Entity Manageru. Jak bych tu továrnu v config.neon dostal do sevice? Díky

mkoubik
Člen | 728
+
0
-

Ne, OrmExtensionkdyby/doctrine registruje jednu službu entity manageru pro každou konfiguraci a v rámci dané služby používá stále stejnou instanci.

Ale můžeš si vytvořit vlastní továrničku, které injektneš @doctrine.default.connection a @doctrine.default.configuration a zavoláš si $em = Kdyby\Doctrine\EntityManager::create($connection, $configuration); ručně kolikrát budeš chtít.

Edit: Teď mě napadlo, že budeš asi potřebovat aby měl každý entity manager vlastní connection, takže to bude trochu složitější. Zkrátka si vykuchej kód z těch definic v extension a dej si ho do vlastní továrny.

Editoval mkoubik (3. 3. 2014 17:28)