Jak správně používat EntityManagerDecorator v různých objektech

Sami_
Člen | 15
+
0
-

Zdravím,

jaký je správný přístup k používání EntityManagerDecoratoru? (dále zkrátím na em)
Například – mám ArticleService, ve které si injectnu em. Tato funkce v této service mi vyrobí entity (Article) a zároveň zavolá svůj em a nasetuje článkům autora (User).

Mám ArticlePresenter (se svým injectnutým em), ve kterém si injectnu ArticleService a nechám si entity vytvořit. Když nyní z presenteru zkusím tyto entity uložit přes $this->em->persist($articles[0]) a $this->em->flush($articles[0]), presenterův em neví o entitách User, které byly článkům nasetovány a vyhodí chybu A new entity was found through the relationship.

Otázka tedy zní – je lepší, když:
1, Se takto em injectuje do každého objektu, který jej potřebuje (Presentery, Servicy…) a snažit se pracovat s entitama tam, kde jsem je přes em vytáhnul

nebo
2, Mít pouze 1 em, který bych si nějak předával a tedy všechny entity by spravoval on

Jsem docela začátečník, nejspíš moje otázka bude znít amatérsky. Rád se nechám poslat do jakékoli dokumentace nebo článku, jen bych rád věděl, jaký postup se upřednostňuje, případně jestli celý princip chápu špatně.

Editoval Sami_ (16. 3. 2021 16:54)

MajklNajt
Člen | 471
+
+1
-

nech si entity manager nainjektuješ kdekoľvek, je to stále jedna služba – jeden a ten istý em – jedna inštancia triedy, problém bude zrejme v tom, ako entitu User setuješ do Article, ukáž tie triedy/metódy

Sami_
Člen | 15
+
0
-

MajklNajt napsal(a):

nech si entity manager nainjektuješ kdekoľvek, je to stále jedna služba – jeden a ten istý em – jedna inštancia triedy, problém bude zrejme v tom, ako entitu User setuješ do Article, ukáž tie triedy/metódy

Super, takže existuje jen 1 instance.
S tím Articles a User to byl příklad, mám Entity: Trade, User a Currency. Zjednodušeně kdo udělal obchod a v jaké měně.

Entita Trade:

/**
 * Class Trade
 * @package App\Model\Database\Entity
 * @ORM\Table
 * @ORM\Entity(repositoryClass="App\Model\Database\Repository\TradeRepository")
 */
class Trade implements \AuthorizationScope
{

	/**
	 * @ORM\Id
	 * @ORM\GeneratedValue
	 * @ORM\Column(type="integer")
	 */
	private int $id = null;

	/**
	 * @ORM\ManyToOne(targetEntity="Currency")
	 */
	private Currency $currency;

	/**
	 * @ORM\ManyToOne(targetEntity="User", inversedBy="trades")
	 */
	private User $user;


	public function setCurrency(Currency $currency): void //... ostatní settery jsou stejné
	{
		$this->currency = $currency;
	}

}

Entita Currency:

/**
 * Class Currency
 * @package App\Model\Database\Entity
 * @ORM\Table
 * @ORM\Entity (repositoryClass="App\Model\Database\Repository\CurrencyRepository")
 */
class Currency
{

	/**
	 * @var string
	 * @ORM\Id
	 * @ORM\Column(type="string", length=3)
	 */
	private string $id;

	/**
	 * @var string
	 * @ORM\Column(type="string", length=64)
	 */
	private string $name;
}

Vytváření Tradu v TradeService:

// $this->user je injectnutý Security/User - neměl by být problém, získám z něj jen ID
function createTrade() {
	$trade = new Trade();
	$trade->setUser($this->em->getRepository(User::class)->find($this->user->getId()));
	// $trade->setCommodity($this->em->getRepository(Commodity::class)->findOneBy(['name' => 'EURUSD'])); Commodity je jen další entita v Trade, vynechal jsem z popisu pro přehlednost
	$trade->setCurrency($this->em->getRepository(Currency::class)->find('CZK'));
	return $trade;
}

TradePresenter:

public function handleAddTrade()
{
	$t = $this->tradeService->createTrade();
	$this->em->persist($t);
	$this->em->flush($t);
}

Je tohle dostačující?

Editoval Sami_ (16. 3. 2021 18:04)

MajklNajt
Člen | 471
+
+1
-

nesypeš tam dáta do nejakej kolekcie OneToMany bez cascade persist? prípadne to vie A new entity was found through the relationship vyhadzovať, keď voláš $em->clear(), ak robíš napr. nejakú dávkovú operácu…

Sami_
Člen | 15
+
0
-

MajklNajt napsal(a):

nesypeš tam dáta do nejakej kolekcie OneToMany bez cascade persist? prípadne to vie A new entity was found through the relationship vyhadzovať, keď voláš $em->clear(), ak robíš napr. nejakú dávkovú operácu…

To vytváření je správně – mám formulář, ve kterém vytvářím entitu stejně (a funguje). Tento use-case je trochu jiný – já si vytvořím několik instancí entity Trade, každé nasetuju Usera, Currency atd. a pak to ukládám do session. Když to chci později z té session uložit do DB, hází to A new entity was found through the relationship. Podívám se na to lépe odpoledne, stále mi není jasné, proč se to děje (pokud si tyto instance neuložím do session a rovnou to sypu do DB, funguje to dle očekávání)

Editoval Sami_ (17. 3. 2021 8:49)

David Matějka
Moderator | 6445
+
+2
-

Ukládat Doctrine entity do session není jednoduché a je lepší se tomu vyhnout. do session ukládej vždy jen ID uložených entit, případně pokud ta entita není persistovaná, tak jen array/stdclass/dto s daty

Sami_
Člen | 15
+
0
-

David Matějka napsal(a):

Ukládat Doctrine entity do session není jednoduché a je lepší se tomu vyhnout. do session ukládej vždy jen ID uložených entit, případně pokud ta entita není persistovaná, tak jen array/stdclass/dto s daty

Díky, už jsem byl poučen, že to nebude fungovat, protože při uložení do session se objekty pravděpodobně serializují. Vyřeším to jinak, všem díky za pomoc. Asi případ uzavřen

Btw. Parádní přednášky, i když už trochu starší, ale dost jsem z toho pochopil :)