Nextras\ORM – ORM nad Nextras\Dbal
- hrach
- Člen | 1838
@Hanz25 ano, v mapperu pretizis metodu, viz. doc https://nextras.org/…/conventions#…
- andros
- Člen | 145
Ahoj, snažím se naučit a používat Nextras ORM a už druhý den se trápím s tímto:
Mám entitu Categorie:
/**
* Category
* @property int $id {primary}
* @property string $name
* @property OneHasMany|Movie[] $movies {1:m Movie::$cat}
*/
class Category extends Entity {
}
Pak mám entitu Filmy:
/**
* Class Movie
* @property int $id {primary}
* @property string $title
* @property int|NULL $category
* @property string|NULL $content
* @property int|NULL $csfdId
* @property string|NULL $year
* @property DateTimeImmutable $createdAt
* @property OneHasMany|Comment[] $comments {1:m Comment::$movies }
* @property ManyHasMany|Tag[] $tags {m:m Tag::$movies, isMain=true}
* @property ManyHasOne|Category[] $cat {m:1 Category::$movies}
*/
class Movie extends Entity {
}
Jeden film může mít přiřazenou jednu kategorie, jedna kategorie, může
mít x filmů
V šabloně mám zhruba toto:
{foreach $movies as $movie}
$movie->title
$movie->cat->name (tady chci zobrazit název kategorie)
{/foreach}
Tabulky v DB mám takto:
CREATE TABLE `categories` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `movies` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`category` int(11) NOT NULL,
`title` varchar(255) DEFAULT NULL,
`content` text,
`csfd_id` int(11) DEFAULT NULL,
`year` varchar(4) DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `year` (`year`),
KEY `category` (`category`),
KEY `csfd_id` (`csfd_id`),
CONSTRAINT `movies_ibfk_1` FOREIGN KEY (`category`) REFERENCES `categories` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Bohužel pořád dostávám chybu:
Property FrontModule\Movie::$cat is not nullable.
Prosím, napadá někoho, kde dělám chybu ?
Editoval andros (16. 5. 2017 20:35)
- Hanz25
- Člen | 38
Ahoj,
tabulky vypadají oka, ale ta definice entity je taková mírně zmatečná. Definuješ zvlášť ten klíč jako obyčejný int sloupec a zároveň jako další property, která je ovšem vztahem.
Já bych definici té entity upravil takto
/**
* Category
* @property int $id {primary}
* @property string $name
* @property Movie[]|NULL $movies {1:m Movie::$category}
*/
/**
* Class Movie
* @property int $id {primary}
* @property string $title
* @property Category $category {m:1 Category::$movies}
* @property string|NULL $content
* @property int|NULL $csfdId
* @property string|NULL $year
* @property DateTimeImmutable $createdAt
* @property Comment[] $comments {1:m Comment::$movies }
* @property Tag[] $tags {m:m Tag::$movies, isMain=true}
*/
– odstranil jsem statementy OneHasMany a ManyHasOne – jsou nepovinné a
zhoršují čitelnost (úplně nevím proč tam jsou)
– sjednotil jsem property $cat a $category do jedné. Nemá cenu (a ani to
snad nejde) to definovat ve dvou propertách, protože pokud chceš jen ten int,
tak se dá nad property zavolat getRawValue().
– odstranil jsem závorky [] u property category (původně cat), protože
odkazuješ na jednu entitu a ty závorky značí že jich bude víc, tedy
odkazují na kolekci
- revager
- Člen | 3
Ahoj,
narazil jsem na problém a vůbec nechápu, proč se to nechová tak, jak by mělo.
Mám entity User, Reservation a UserReservation
<?php
/**
* @property int $id {primary}
* @property Block $start {m:1 Block, oneSided=true}
* @property Block $end {m:1 Block, oneSided=true}
* @property User $user {m:1 User, oneSided=true}
* @property int $numberOfReservations
* @property int $maxNumberOfReservations
* @property DateTime $date
* @property string $note
*/
class Reservation extends Entity
{
}
?>
<?php
/**
* @property int $id {primary}
* @property string|null $uid
* @property int $cuniPersonalId
* @property string $email
* @property string|null $name
* @property string $role
* @property string|null $data
*/
class User extends Entity
{
}
?>
<?php
/**
* @property int $id {primary}
* @property User $user_id {m:1 User, oneSided=true}
* @property Reservation $reservation_id {m:1 Reservation, oneSided=true}
* @property DateTime $created_at
*/
class UserReservation extends Entity
{
}
?>
UserReservation je spojovací tabulka
CREATE TABLE `user_reservation` (
`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
`user_id` int(11) NOT NULL,
`reservation_id` int(11) NOT NULL,
`created_at` date NOT NULL,
FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE,
FOREIGN KEY (`reservation_id`) REFERENCES `reservation` (`id`) ON DELETE CASCADE
);
Když chci získat data například tímto způsobem:
<?php
$userReservations = $this->orm->UserReservations->findBy(['reservation_id' => $reservationId]);
foreach ($userReservations as $userReservation) {
dump($userReservation->user_id);
}
?>
tak mi to padne na chybě:
Property App\Orm\UserReservation::$user_id is not nullable.
Jediné, co mi to vrátí, je id záznamu. Zbytek je null.
Dotaz, který ORM generuje, je v pořádku a vrací přesně to, co lze očekávat. Bohužel si to nějak nerozumí s entitou.
SELECT `user_reservation`.* FROM `user_reservation` AS `user_reservation` WHERE `user_reservation`.`reservation_id` = '1'
Nevěděl by někdo, kde dělám chybu? Děkuji za jakoukoliv radu či tip :).
- hrach
- Člen | 1838
@revager v UserReservation by se property mely jmenovat bez suffixu _id (pokud je nastaven v db spravne cizi klic). Viz dokumentace https://nextras.org/…/conventions#…
- revager
- Člen | 3
hrach napsal(a):
@revager v UserReservation by se property mely jmenovat bez suffixu _id (pokud je nastaven v db spravne cizi klic). Viz dokumentace https://nextras.org/…/conventions#…
@hrach Mockrát děkuju :)
Editoval revager (20. 6. 2017 20:48)
- Lizardor
- Člen | 35
Zdravím setkal se někdo s problémem že když nastavím
dbal:
simpleStorageTz: ‚Europe/Prague‘
tak DateTime který vytvořím a uložím do DB je v pořádku, ale když ho načtu tak mám –2h.
Když ten simpleStorage nepoužiji, tak se mi od DB DateTime uloží o –2h. ale zas načte (v PHP) v klasickém času, nějáké nápady jak tohle vyřešit?
- Felix
- Nette Core | 1245
Lizardor napsal(a):
Zdravím setkal se někdo s problémem že když nastavím
dbal:
simpleStorageTz: ‚Europe/Prague‘tak DateTime který vytvořím a uložím do DB je v pořádku, ale když ho načtu tak mám –2h.
Když ten simpleStorage nepoužiji, tak se mi od DB DateTime uloží o –2h. ale zas načte (v PHP) v klasickém času, nějáké nápady jak tohle vyřešit?
Jojo stalo, zvyknul jsem si, ze v DB to mam o trochu mene, ale verim, ze je na to lepsi reseni.
- Lizardor
- Člen | 35
Nedalo mi to a nakonec sem to vyřešil takhle
dbal:
simpleStorageTz: 'Europe/Prague'
connectionTz: 'Europe/Prague'
php:
date.timezone: Europe/Prague
tohle jediný mi funguje. Jinak kde nelze nainstalovat timezony tak to asi není řešení no.
Editoval Lizardor (24. 7. 2017 13:12)
- hrach
- Člen | 1838
Podstatný je, jaký typ sloupce používáš. MySQL nebo PostgreSQL se pak chovají jinak a orm se tomu prizpusobi. Nicméně od verze 3.0 by se to mělo chovat inteligentneji.
Pokud byste chtěli poradit, hoďte sem svojí konfiguraci orm, timezonu ve které běží MySQL, ve které běží php, typ sloupců.
- David Klouček
- Člen | 57
Jakej je vlastně cíl Nextras\ORM? Když má identity mapu a je to teda plnohodnotný ORM (narozdíl od třeba LeanMapperu), je nějakej důvod ho použít místo nejrozšířenější Doctrine 2?
A ještě jedna věc, proč snad u všechny ORM autorů z Nette komunity používaj poddotazy místo joinů?
- hrach
- Člen | 1838
@DavidKlouček
Jakej je vlastně cíl Nextras\ORM?
Dodat kvalitni ORM pro PHP.
Když má identity mapu a je to teda plnohodnotný ORM, je nějakej důvod ho použít místo nejrozšířenější Doctrine 2?
Urcite. Doctrine2 ma plno vlastnosti, ktere nemuseji vyhovovat. Uz jsem se o tom nekde rozepisoval, ale nemuzu to ted najit. Osobne mi na Doctrine nevyhovuji tyto vlastnosti, ktery ma nextras poreseny:
- lazy loading relationships: v Doctine to napriklad nefunguje u ManyHasOne.
- clever loading of relationship: v Doctrine na to musis myslet dopredu, v Nextras mas na repository definovany obecny gettery, vede to k trochu vic reusable architekture.
- definice entity: je to dost vec vkusu, ale v Nextras se vleze na screen, takze se lepe ziska prehled
- edge case vlastnosti: napr. v Doctrine nelze u MySQL ziskat id, nez udelam flush, protoze persist realne nevola jeste dotaz (insert) do db. Takova blbost, ale dost dulezita. U Postgre se chova Doctrine lepe diky sekvencim.
A ještě jedna věc, proč snad u všechny ORM autorů z Nette komunity používaj poddotazy místo joinů?
U Nextras se poddotazy naopak nepouzivaji. (Temer, jediny pouziti je pro nektere count dotazy, ale tam by join jaksi moc nepomohlo.) Pro filtering se pouziva join, pro vybrani dat se pouzivaji nove dotazy. Ale to nejsou poddotazy. :)
Editoval hrach (24. 7. 2017 20:23)
- Čamo
- Člen | 798
Zdravím,
u Nette Database je možné pridať do konfigurácie options. Napr:
username: root
password: root
options:
PDO::MYSQL_ATTR_INIT_COMMAND: 'SET sql_mode="NO_ENGINE_SUBSTITUTION"'
Je možné to pridať aj do dbal sekcie?
dbal
...
password:
username: root
options:
PDO::MYSQL_ATTR_INIT_COMMAND: 'SET sql_mode="NO_ENGINE_SUBSTITUTION"'
Ďakujem.
- Felix
- Nette Core | 1245
stajo napsal(a):
zdravim,
ako v teste vytvorim entitu bez hlasky:
Nextras\Orm\InvalidStateException: MetadataStorage::get() called too early.
Been there: https://github.com/…m/issues/181
Aktualne to neni mozne, ale premyslim o tom, ze bych neco maleho sesmolil, aby to slo. :-)
- stajo
- Člen | 8
Been there: https://github.com/…m/issues/181
Aktualne to neni mozne, ale premyslim o tom, ze bych neco maleho sesmolil, aby to slo. :-)
nj, to som nasiel, kym som sem napisal. akurat mi neslo do hlavy, ze to je rok stare.
to sa fakt neda nejako normalne napisat unit test s entitou?
- hrach
- Člen | 1838
@Čamo Muzes sql mode nastavit primo z konfiguracniho pole, viz.: https://nextras.org/dbal/docs/3.0/. Pripadne napis, jake jine konfigurace te zajimaji.
- hrach
- Člen | 1838
to sa fakt neda nejako normalne napisat unit test s entitou?
@stajo on to pak neni moc unit test, kdyz tam passujes celou Entitu. Tak tam posilej IEntity, respektive mock tve entity.
Proste aby ORM dobre fungovalo a bylo propojene s ostatnimi entitami, potrebuje mit dobra metadata, a ty neni jednoduche vytvorit. Obecne by me zajimalo, jak ten test presne pisete? @Felix
Editoval hrach (13. 8. 2017 14:49)
- Felix
- Nette Core | 1245
hrach napsal(a):
to sa fakt neda nejako normalne napisat unit test s entitou?
@stajo on to pak neni moc unit test, kdyz tam passujes celou Entitu. Tak tam posilej IEntity, respektive mock tve entity.
Proste aby ORM dobre fungovalo a bylo propojene s ostatnimi entitami, potrebuje mit dobra metadata, a ty neni jednoduche vytvorit. Obecne by me zajimalo, jak ten test presne pisete? @Felix
Napriklad urcite workflow ve fasadach, kdy se meni stavy entity a dalsi veci. Mocky tedka vyuzivam, ale radeji bych realnou entitu.
- Vyki
- Člen | 388
Ahoj, chtěl jsem se zeptat, zda lze pomocí Nextras\Orm
jednoduše získat i výsledek dotazu s agregační funkcí, nebo musím
položit dotaz přes Nextras\Dbal\Connection
. Jde mi o to, že
chci zjistit MAX(hodnotu)
a MIN(hodnotu)
sloupce
v tabulce a nejraději bych to měl v repository jako metodu, ale patrně by
to pak popíralo smysl ORM.
Díky
- David Matějka
- Moderator | 6445
@Vyki ahoj, tohle patri do mapperu, kde napises SQL a pak se na to budes dotazovat skrz repozitar pres proxy
- Vyki
- Člen | 388
@DavidMatějka Díky za nasměrování. Nakonec jsem našel example zde: https://nextras.org/…2/repository#…
- Hologos
- Člen | 19
@hrach Napsal jsem to blbě – chtěl bych si vytvořit db tabulky pomocí Symfony Console a chtěl jsem si nějak z ORM vytáhnout Nextras\Dbal\Connection. Nenašel jsem na to žádnou metodu, jedině vytvořit Mapperu metodu, která to vrátí, ale to se mi moc nelíbilo, protože to je na testy a nechci, aby to bylo přístupné z aplikace. Nakonec jsem to udělal přes inject property. I tak mě zajímá, jestli je nějak možné se dostat k Nextras\Dbal\Connection z Modelu (Nextras\Orm\Model\Model).
- Hologos
- Člen | 19
Ahoj,
mám obrovský problém s výkonností ORM. Udělal jsem sample aplikaci, kde trasuju časy. Na lokálu je PHP 5.6.31, na hostingu 5.6.30. Používám Nextras/ORM 2.2 a Nextras\Dbal 3.0.
V DB jsou 2 tabulky Set a Cards. Tabulka sets má 1 záznam, tabulka cards má asi 300 záznamů.
Entity
<?php
namespace App\Model\Orm;
use Nextras\Orm\Entity\Entity;
use Nextras\Orm\Relationships\OneHasMany;
/**
* @property int $id {primary}
* @property string $code
* @property string $name
* @property string $type
* @property DateTime $releaseDate
* @property int $active {default self::NOT_ACTIVE}
* @property OneHasMany|Card[] $cards {1:m Card::$set, orderBy=name}
*/
class Set extends Entity
{
const NOT_ACTIVE = 0;
const ACTIVE = 1;
}
/**
* @property string $id {primary}
* @property string|NULL $multiverseId
* @property string $name
* @property string|NULL $number
* @property string|NULL $imageName
* @property string $rarity {enum self::RARITY_*}
* @property int $active {default self::NOT_ACTIVE}
* @property Set $set {m:1 Set::$cards}
*/
class Card extends Entity
{
const NOT_ACTIVE = 0;
const ACTIVE = 1;
const RARITY_COMMON = 'c';
const RARITY_UNCOMMON = 'u';
const RARITY_RARE = 'r';
const RARITY_MYTHIC = 'm';
const RARITY_SPECIAL = 's';
const RARITY_BASIC_LAND = 'b';
}
?>
Tabulky mají v databázi indexy:
sets
PRIMARY id
UNIQUE code
INDEX type
INDEX release_date
cards
PRIMARY id
INDEX set, name
INDEX name
<?php
$sets = $this->orm->sets->findBy(['type' => 'expansion'])->orderBy('releaseDate', ICollection::DESC);
Debugger::timer('overall');
foreach($sets as $set)
{
Debugger::timer('cards');
$cards = $this->sets->cards;
foreach($cards as $card) {} // aby se provedlo načtení
Debugger::log('Retrieving cards took '. number_format(Debugger::timer('cards'), 2, ',', ' ') .'s.');
foreach($cards as $card)
{
// zatim neni potreba resit
}
}
Debugger::log('Overall time '. number_format(Debugger::timer('overall'), 2, ',', ' ') .'s.');
?>
A výstup je
<?php
Retrieving cards took 6,53s.
Overall time 6,68s.
?>
Zkoušel jsem to nahrát i na hosting, a tam jsou časy ± totožné. Zajímavé je, že když se podívám to Tracy DebugBaru, tak tam ty SQL dotazy se vykonaj za pár milisekund. Jestli to chápu správně, tak má takovou režii samotný ORM framework? Cílový stav aplikace, že tabulka sets bude mít cca 400 záznamů a tabulka cards bude mít cca 35 000 záznamů. Pokud by časy ještě více stoupaly, tak to je skoro neúnosné.
<?php
SQL query Time (ms)
SELECT `sets`.* FROM `sets` AS `sets` WHERE `sets`.`type` = 'expansion' ORDER BY `sets`.`release_date` DESC 0.423
SELECT `cards`.* FROM `cards` AS `cards` WHERE `cards`.`set` IN (1) ORDER BY `cards`.`name` 0.730
?>
Editoval Hologos (18. 9. 2017 14:35)
- hrach
- Člen | 1838
- uplne si nejsem jist, ze je nextras orm 2.2 kompatibilni s dbalem 3.0
- v php 7.0 je vse dvojnasobne rychlejsi, to jen sidenote
- vzhledem k tomu, ze dbal 3.0 vyzaduje php 7.0, nevim, jak ti to muze fungovat
- nedava smysl, aby neco trvalo takto dlouho, muze to byt bug, muze to byt neco spatne, byt nevim moc co
- mas vypnuty xdebug?
- totozne casy na hostingu – to jen spis dava tusit, ze je neco spatne, pokud teda nemas spatny hosting a vyborne pc
- pripadne muzes zkusit nextras orm demo, vytvorit 300 komentaru k clanku a mrknout cas nacitani dany stranky, jestli je taky tak spatny.
- Lizardor
- Člen | 35
Zdravím chci se zeptat zda-li se někdo nesetkal s tímto problém. Jde o to že vybírám velké množství řádku (cca 25k) a limituju to třeba na 1000, dotaz je rychlý v clientu a v tracy taky, cca 16–20ms (je tam hodně joinu) ale pokud si to profiluju (i na produkci), tak se dostanu na 200–300ms konkrétně tahle část
$result = $this->connection->queryArgs($builder->getQuerySql(), $builder->getQueryParameters());
Pokud dotaz napíšu klasickým query je výsledek totožný. Není tam nějáký problém s „LIMIT“ ?
Editoval Lizardor (21. 9. 2017 16:57)
- majky358
- Člen | 37
Mám vzťah M:1, názov stĺpcu v zdrojovej tabuľke je user_account_id, názov property musím mať $userAccount, používam prefixy aj v iných tabuľkách.
* Class UserMessage
* @property User $user {m:1 User::$messages}
* Class User
* @property UserMessage[]|NULL $messages {1:m UserMessage::$user}
//Result: UserMessage::$user is not nullable
//funguje OK
* Class UserMessage
* @property User $userAccount {m:1 User, oneSided=true}
V createStorageReflection volám setMapping a zmením názov, nejaký iný elegantnejší spôsob ? :)
Editoval majky358 (25. 9. 2017 16:26)
- Zax
- Člen | 370
Ahoj, narazil jsem na jednu takovou WTF vlastnost, která snad ani není bug, jen prostě… WTF.
Jde o to, že v některých situacích čtení z property zavolá její setter.
__get()
→ getValue()
→
internalGetValue()
→ initProperty()
→
internalSetValue()
→ setter*()
Což může vést k zajímavým „efektům“, např.:
<?php
/**
* @property int $id {primary}
* @property OneHasMany|Child[] $children {1:m Child::$user}
*/
class User extends Entity {}
/**
* @property int $id {primary}
* @property User $user {m:1 User::$children}
* @property string $personalId
*/
class Child extends Entity {
public function __construct(User $user, $personalId) {
$this->user = $user;
$this->personalId = $personalId;
}
protected function setterPersonalId($value) {
$this->throwIfDuplicate($value);
return $value;
}
private function throwIfDuplicate($personalId) {
foreach($this->user->children as $child) {
if($child === $this) {
continue;
}
if($child->personalId === $personalId) { // problém - zavolá setterPersonalId nad $child a spustí celý kolotoč znovu
throw new DuplicateChildException;
}
}
}
}
?>
Nejspíš to jen blbě používám, ale každopádně mi to přijde, že se taková chyba může stát každému celkem snadno. Mít validaci v setteru mi přijde logické (resp. jde o pochopitelný zvyk z klasických public setterů), naopak bych nečekal, že se bude volat setter když čtu – nicméně ono to zjevně svůj důvod má, proto mi to vlastně nepřijde jako bug a hádám, že to není rozumně řešitelný.
Jinak musím ORMko pochválit, jedním očkem sleduju vývoj od začátku (fíha, to už uběhly 3 roky?) a vypadá super! Na menší projekty kde člověk nechce vytahovat Doctrinu vypadá jako velmi dobrá volba. Díky :-)
Editoval Zax (28. 9. 2017 0:40)
- Milan Obrtlík
- Člen | 50
Mějme SQL dotaz
select * from book
join book_x_tag as bt on book.id = bt.book
join tag on tag.id = bt.tag
join book_x_author as ba on book.id = ba.book
join author author.id = ba.author
where author.id = 1 and tag.id IN (1,2,3,4,5,7)
Pomocí tohoto dotazu získám knihy, které napsal autor 1 a zároveň
mají tagy 1 až 7.
Poradíte mi prosím jak tento dotaz přepsat do Nextras/ORM?
- Čamo
- Člen | 798
Zdravím,
prosím vás čo robím špatne na používaní builderu v maperi?
public function findMedicalPlansToProgressComponent( )
{
$this->builder()
->andWhere('start < %dt', DateTime::from('now'))
->andWhere('end > %dt', DateTime::from('now'));
return $this->builder();
}
Ono to vracia kolekciu ale vôbec to neberie do úvahy tie podmienky.
Vypadne z toho sql
SELECT `medical_plans`.* FROM `medical_plans` AS `medical_plans`
A to ešte netuším ako do toho dostanem join …
Editoval Čamo (3. 10. 2017 16:39)
- hrach
- Člen | 1838
@Zax yes, to je aktualni chovani a je o tom, ze proste nacitani dat z db musi projit setterem (aby se treba nejaka data znormalizovala). Mel jsem pocit, ze uz jsem kolem toho neco resil do 3.0, ale nemuzu ted najit zadny konkretni commmit. Mozna by se to mohlo nejak zmenit. Muzes zkusit pouzit metodu getRawValue(), ktera nespusti ten setter (ale muzes dostat nenormalizovanou hodnotu, coz by u stringu ale nemel byt moc problem).
@MilanObrtlík no, dle tveho popisu to podle me je o tom, ze nema mit tagy 1–7, ale jeden tak v 1–7. Jinak nevim, na jake vrstve te to zajima, ale tento konkretni dotaz by mohl byt nasledovne:
$booksRespository->findBy(['this->authors->id' => 1, 'this->tags->id' => [1, 2, 3, 4, 5, 6, 7]]);
@Čamo je to tak :-) Metoda builder() vzdy vraci novou instanci builder.
- majky358
- Člen | 37
Mám dve entity, vzťah majú 1:1
//Address => @property User $user {1:1 Address::$address, isMain=true}
//User => @property Address $address {1:1 User::$user}
$user = new User();
//...
$userRepository->persist($user);
$address = new Address();
$address->user = $user;
$addressRepository->persist($address);
$user->address = $address;
//$user->setAsModified() | $userRepository->doPersist($user) | $userRepository->persist($user) => neprejde UPDATE
$model->flush();
Aký je správny postup ak chcem spraviť update user entity ? Došiel som len na riešenie volať $addressRepository->persist($address, $withCascade = false); ale aj tam som mal narazil na problém, že sa mi spraví udpate entity ale ref entity address nieje obsiahnutá v update dotaze. Ďakujem
Editoval majky358 (5. 10. 2017 1:27)
- Hologos
- Člen | 19
Ahoj,
narazil jsem na zajímavý problém a nevím, jak je vyřešit. Mám 2 entity, které jsou mezi s sebou 2× provázané vazbou ManyHasMany a generuje mi to pro oba případy shodné názvy vazebních tabulek. Jak z toho ven?
Skupina (Group) může mít 1 až N vlastníků (User) a vlastník (User)
může vlastnit 0 až N skupin.
Skupina (Group) se skládá z 0 až N hráčů (User) a hráč může být
v 0 až N skupinách (Group).
<?php
namespace App\Model\Orm;
use Nextras\Orm\Entity\Entity;
use Nextras\Orm\Relationships\ManyHasMany;
/**
* @property int $id {primary}
* @property ManyHasMany|Group[] $ownedGroups {m:m Group::$owners, isMain=true}
* @property ManyHasMany|Group[] $groupsIamMemberOf {m:m Group::$members, isMain=true}
*/
class User extends Entity
{
}
/**
* @property int $id {primary}
* @property ManyHasMany|User[] $owners {m:m User::$ownedGroups}
* @property ManyHasMany|User[] $members {m:m User::$groupsIamMemberOf}
*/
class Group extends Entity
{
}
?>
Edit: V jedné přednášce (ještě ke starému Orm) si zmínil, že bys to řešil pomocí více entit. Když nad tím přemýšlím, tak je to tak určitě lepší pro budoucí vývoj, protože se pak může změnit požadavek, že GroupMember nemusí být nutně registrovaný uživatel. I tak to tu nechám, zajímá mě aktuální názor.
Editoval Hologos (13. 10. 2017 9:03)