Továrna pro EntityManager
- Čejen
- Člen | 4
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í):
- Formou Extension
- 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
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
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
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
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
Ne, OrmExtension
z kdyby/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)