Nextras ORM – přístup k datům v spojovací tabulce

Fires
Člen | 97
+
+2
-

Zdravím, mám 3 tabulky (item, storage, item_x_storage). Mám nastavené v nextras orm, všechny entity a přechod mezi item na storage a zpět přes ManyHasMany funguje. Ve spojovací tabulce item_x_storage mám navíc ale uložené množství.(předmět může být ve více uložištích v různých množstvích) Je nějaká možnost se k těmto datům (sloupec item_x_storage.quantity) dostat v rámci Relations? Nebo jak toto řešit ? Pročetl jsem dokumentaci ale dělám s Nextras ORM poprvé a jsem tom dost zamotaný :( Díky moc

dms
Člen | 93
+
0
-

Bohuzel se tam dostat neda. Jedine tak, ze udelas dalsi entitu na tu m:m tabulku a budes mit proste 3 entity. Tohle ma eloquent resene jako pivot table a je to nastesti jen jedna z par veci, ktere v nextras chybi.

Fires
Člen | 97
+
0
-

Další entita to bude pak generovat více dotazů do db. Musel bych získat tedy item z nej storage a pak podle id itemu a id storage vytahnout množství. Nějaká možnost jak udělat elegantněji návrh db? Tohle je myslím dost častý případ kdy jsou dvě entity spojené s nejakým parametrem.

hrach
Člen | 1838
+
+3
-

Jak byste si predstavovali, ze by se s takovym sloupcem melo v ORM pracovat?

Fires
Člen | 97
+
0
-

Líbilo by se mi třeba kdyby orm udělalo na entitě „proxy“ variable. $item->storage->quantity ? $storage->item->quantity?

Pavel Kravčík
Člen | 1194
+
0
-

Kromě toho návrhů výše:

  • Používáme taky „simple“ ORM (90% aplikace jednoduché entity, formuláře), ale na složitější dotazy je úplně v pohodě IMHO použít klasický Explorer (select(item_x_storage.storage.quantity)->group() etc).
  • Na krátký výpis do šablony občas v menším projektu (fetchPairs(‚storage.id‘, ‚quantity‘)) a šablona výpis $pairs[id] dle ORM v nějakém foreach
  • Občas pohled v DB nad kterým je entita s readonly sloupci, pokud trváš na ORM (ale nevím jestli to Nextras používá)
mskocik
Člen | 61
+
+1
-

Ďalší návrh: v entite k danej property pridať modifikátor.

/**
 * @property int $quantity {relational column=quantity}
 */
class Storage extends Entity {}

A klasicky zvládať aj insert.

$storage = new Storage();
// ...
$storage->quantity = 2;

$item->add($storage);
hrach
Člen | 1838
+
+1
-

No ta kvantita je na vztahu Storage & Item, takze neni tak uplne jednoduche/jasne z navrzeneho zapisu, o kvantitu jakeho itemu se jedna. Protoze ORM ma identity mapu, entita Storage existuje jednou, tj. teoreticky potrebuje obhospodarit n kvantit pro n itemu.

Ja si nejake API umim predstavit, ale neni to nic hezkeho, respektive nic s cim by se hezky pracovala, a to nemluvim o implementacni narocnosti.

/**
 * @property int $quantity
 */
class StorageItemMetadata extends ManyHasManyMetadata {}

$storage->items->add($item, new StorageItemMetadata(3));
Marek Bartoš
Nette Blogger | 1260
+
+1
-

To je takový „chci používat orm, ale teď zrovna ho použít nechci“

Pokud jde jen o to ta data vytáhnout efektivně, tak by dávalo smysl řešit, jak vylepšit dotazování. Místo řešení, jak nenapsat jednoduchou entitu.

Fires
Člen | 97
+
0
-

Marek Bartoš napsal(a):

To je takový „chci používat orm, ale teď zrovna ho použít nechci“

Pokud jde jen o to ta data vytáhnout efektivně, tak by dávalo smysl řešit, jak vylepšit dotazování. Místo řešení, jak nenapsat jednoduchou entitu.

Řešení to samozřejmě má. Jde jen o to že by to bylo pěkné mít to v rámci orm.

$item = $this->orm->item->getById(12)
foreach($item->storage as $storage){
	$quantity = $storage->quantity;
}

vypádá lépe než

$item = $this->orm->item->getById(12)
foreach($item->storage as $storage){
	$quantity = $this->orm->storageQuantity->getBy(["itemId"=>$item->id,"storageId"=>$storage->id]);
}
mskocik
Člen | 61
+
0
-

Ono to ma zaujimavo eloquent, ako tu uz zaznelo:

return $this->belongsToMany(Role::class)->withPivot('active', 'created_by');

Ale to platí len pre dotazovanie asi (moc do hlbky som to neskumal), neviem ako sa to tam robi pri inserte.

Bolo by fajn, kebyze to ORM umoznuje, ale da sa zit aj bez toho, kedze riesenie existuje. Len clovek namiesto 2 entit definuje 3.

hrach
Člen | 1838
+
0
-

Řešení to samozřejmě má. Jde jen o to že by to bylo pěkné mít to v rámci orm.

$item = $this->orm->item->getById(12)
foreach($item->storage as $storage){
	$quantity = $storage->quantity;
}

To je ten problem. Storage je stejna instance az uz je vytazena pres item#12 nebo item#13, protoze IdentityMapa.
Takto to fungovat nemuze.

hrach
Člen | 1838
+
0
-

Díky za odkaz na Eloquent – to automaticke injectovani spravneho pivotu je zajimave:

use App\Models\User;

$user = User::find(1);

foreach ($user->roles as $role) {
    echo $role->pivot->created_at;
}

Trochu se to podoba tem Metadata, co jsem sdilel nahore, tzn. nutnost define te spojovaci tridy. Akorat timto API by to bylo asi akceptovatelnejsi. Bohuzel si myslim, ze to nebude bezpecne fungovat.

Neco podobneho uz mame v Orm, ze podle toho, odkud entitu accessujes, se pouzije preoptimalizace pro dotazeni dat odjinud. Tzn. jedna se o performance optimalizaci. Meneni ale pivotu podle toho, odkud clovek na entitu prisel, mi prijde extremne nebezpecne. A vlastne v Eloquentu je to mozne jen proto, ze nemaji IdentityMapu, jestli jsem to spravne pochopil.

Marek Bartoš
Nette Blogger | 1260
+
0
-

Je to tak, eloquent identity mapu nemá.

Fires
Člen | 97
+
0
-

hrach napsal(a):

Řešení to samozřejmě má. Jde jen o to že by to bylo pěkné mít to v rámci orm.

$item = $this->orm->item->getById(12)
foreach($item->storage as $storage){
	$quantity = $storage->quantity;
}

To je ten problem. Storage je stejna instance az uz je vytazena pres item#12 nebo item#13, protoze IdentityMapa.
Takto to fungovat nemuze.

To je stejná instanace storage i když item12 a item13 každý má napárovaný jiný storage ?

hrach
Člen | 1838
+
+2
-

To je stejná instanace storage i když item12 a item13 každý má napárovaný jiný storage ?

Je to M:N relationship, takze mohou mit nejaky stejny storage a pak to je stejna instance.

dms
Člen | 93
+
0
-

U nás úplně základní příklad, kdy máme entitu Product a Category a zadání je mít možnost řadit v každé kategorii produkty jinak. K tomu se perfektně hodí tabulka m:m se sloupcem position navíc. Aktuálně to řešíme přes 3 entity, ale je to trochu takový kostrbatý ta práce s tím. Zde je jasné, že tohle prostě integrovat do ORM není úplně easy a asi se zde budeme muset smířit s více entitami.

Když už se tu řeší tohle tak bych měl taky jednu takovou prkotinu, která je navíc v eloquentu a to je firstOrCreate. Tedy v nextras by to bylo něco jako getByOrCreate. V praxi to zkracuje takový ten rutinní zápis, kdy kontrolujeme vrácenou entitu vůči null a pak ji vytváříme když není a attachujeme… Ano je možné si to napsat do nějakého abstract repository, ale radši bych byl za interní integraci. trochu info k tomu zde: https://laravel-news.com/…dateorcreate

Jedeme většinu aplikací v nextras/orm ale občas je dobré se inspirovat jak to mají dělané jinde a ulehčit si to