Nextras ORM – přístup k datům v spojovací tabulce
- Fires
- Člen | 97
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
- Fires
- Člen | 97
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.
- Pavel Kravčík
- Člen | 1194
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á)
- hrach
- Člen | 1838
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
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
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
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
Ř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
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.
- Fires
- Člen | 97
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 ?
- dms
- Člen | 93
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