Nextras Orm defalutni filtrovani
- tomasde
- Člen | 26
Mam otazku jak nastavit defaultni filtrovani kdyz mam treba vypis takto
entity1 = $orm->entita1->findBy([
ICollection::OR,
['time' => null],
['time>=' => $now],
])->orderBy('time', ICollection::ASC_NULLS_LAST);
foreach($entity1 as $entita1){
foreach($entita1->movie->events as $event){
dump ($event->time);
}
}
Vytvori se Mysql dotaz
SELECT `events`.* FROM `events` AS `events` WHERE `events`.`movie_id` IN ('1', '2');
Jenze ja potrebuju aby se ty eventy filtrovali jeste podle time >= NOW()
SELECT `events`.* FROM `events` AS `events` WHERE `events`.`movie_id` IN ('1', '2') AND `events`.`time` >=NOW();
Pokazde kdyz budu chtit vytahnout eventy tak je chci mit vzdy vetsi nez je aktualni cas.
Nejde nekde zadat callback nebo naka metoda ?
Zkousel jsem to udelal tak, ze v Movie budu mit metodu getEvents(); a v ni
public function getEvents(): ICollection {
return $this->events->toCollection()->findBy(['time>=' => new \DateTime()]);;
}
jenze ja si potrebuju prvne zjistit jestli ten movie hasEvents();
public function hasEvents():bool{
return count($this->events) > 0;
} // tady se mi zavola sql prikaz bez toho filtrovani time
// Tohle nefunguje to se vytvori dokonce 3x sql dotazy na events
public function hasEvents():bool{
$this->getEvents();
return count($this->events) > 0;
}
Zkousel jsem i pretizit v repository metody jako findByIds nebo findBy tyhle metody nejsou vubec volany
Editoval tomasde (26. 1. 13:33)
- tomasde
- Člen | 26
to jsem prave ze zkousel a udela se to, ze se mi vytvori tolikrat sql dotaz kolik mam vypis z prvni tabulky
SELECT `m_vorschau`.* FROM `m_vorschau` AS `m_vorschau` WHERE (`m_vorschau`.`time` IS NULL) OR (`m_vorschau`.`time` >= '2025-01-26 16:07:06.498593') ORDER BY `m_vorschau`.`time` IS NULL, `m_vorschau`.`time` ASC
SELECT `m_movies`.* FROM `m_movies` AS `m_movies` WHERE `m_movies`.`id` IN ('4f70abf3', '5f725b80', '0f1b0eed')
SELECT `m_events`.* FROM `m_events` AS `m_events` WHERE (`m_events`.`time` >= '2025-01-26 16:07:06.535753') AND (`m_events`.`movie_id` IN ('0f1b0eed', '4f70abf3', '5f725b80'))
SELECT `m_events`.* FROM `m_events` AS `m_events` WHERE (`m_events`.`time` >= '2025-01-26 16:07:06.552022') AND (`m_events`.`movie_id` IN ('0f1b0eed', '4f70abf3', '5f725b80'))
SELECT `m_events`.* FROM `m_events` AS `m_events` WHERE (`m_events`.`time` >= '2025-01-26 16:07:06.553081') AND (`m_events`.`movie_id` IN ('0f1b0eed', '4f70abf3', '5f725b80'))
To chce ten filter zadat nekam jeste predtim nez si ty events vyzadam, aby to
pak vyjelo vsechno dohromady v jednom dotazu.
Aby trida OneToMany zavolalo nakou callback funkci pokud budu vyzadovat ty
events.
Skoda ze to nevola EventsRepository, tam bych to v nake pretizene metode
pridal.
Editoval tomasde (26. 1. 16:23)
- hrach
- Člen | 1844
@tomasde to vypada, ze je problem v tom, ze kdykoliv se to getEvents() vola, mas v podmince jiny cas (now). Jednoduchy fix je vymazat tomu casu microsecond – a nebo si nekde ten time ulozis a posles do toho getEvets() jen tu jednu – vzdy stejnou instanci casu.
PS: vzhledem k tomu, jak ma php blby API na datetime, tak mozna ta druha verze je jednodussi.
- tomasde
- Člen | 26
neni lepsi tam napsat toto ?
return $this->events->toCollection()->findBy(['time>=' => 'NOW()']);
Ale rve to ze to chce Datetime, ma dbal literal neco jako ma nette database ?
Mimochodem Ai je uplne k hounu vymejsli si neexistujici tridy a metody
Kdyz to nevi tak si to vymysli nakou kravinu, hlavne aby to neco napsalo.
Editoval tomasde (27. 1. 12:17)
- m.brecher
- Generous Backer | 905
@tomasde
Mimochodem Ai je uplne k hounu
Jaké AI používáš ? Já používám free Copilot dostupný v prohlížeči Edge a zadávám pečlivě formulované prompty v angličtině. Na dotazy z oblasti masových technologií (css, javascript, PHP, OOP, Git, phpStorm, composer) dostávám špičkové odpovědi, obvykle řádově lépe formulované než když pošlu dotaz na fórum. Mě přijde AI jako skvělý nástroj, denně posílám desítky promptů. To, že někdy odpoví nesmysl je v pořádku – algoritmy AI jsou inspirované strukturou lidského mozku (neuronová síť). Nelámej nad AI hůl on člověk musí používáním přijít na to, jak to efektivně použít.
- hrach
- Člen | 1844
@tomasde no, teoreticky by bylo, ale toto v Nextras ORM zaspat nejde.
napr. proto, te v tom $events
muzes mit nejaky nepersistovany
relationship (tzn. co v db jeste neni) a bude to porad spravne fungovat.
Dostat datetime bez mirkosekund muzes takto: (chatgpt):
function getCurrentDateTime(): DateTime {
return DateTime::createFromFormat('Y-m-d H:i:s', (new DateTime())->format('Y-m-d H:i:s'));
}
- tomasde
- Člen | 26
ja se ale ptal primo na sql dotaz NOW()
vsak je lepsi napsat NOW() nez vytvaret toto
return DateTime::createFromFormat('Y-m-d H:i:s', (new DateTime())->format('Y-m-d H:i:s'));
Proto jsem psal ze ai je blba protoze jsem se ptal kde mohu zadat sql literal
a ona si vymysli neexistujici tridy a metody.
Protoze je ocekavano datetime ale mela by byt i moznost pouzit NOW()
- Marek Bartoš
- Nette Blogger | 1309
mela by byt i moznost pouzit NOW()
No, neměla. ORM je abstrakce nad databází, snaží se tě od ní odstínit. Jen tak může fungovat beze změn v kódu nad různými databázemi i s jinými úložišti dat. Cokoli pro specifické úložiště patří do mapperu a collection functions.
V tvém případě se vytváří nové dotazy nejspíš kvůli tomu, že
čas který předáváš se pokaždé liší. Možně řešení je vytvořit si
jednu instanci DateTime a do všech findBy předávat tu, namísto toho abys
pokaždé vytvářel novou.
Ideálně si však kolekci profiltrovanou skrze findBy vytvoř jen jednou a
předávej si všude tu, namísto opakovaného volání findBy.
- tomasde
- Člen | 26
Dobre diky.
Jeste bych mel otazku, jak udelat
Nebo jak docilit toho, kdyz si vyjedu entity
$entita = $this->orm->entityRepository->findByIds([array_keys($pole)])->fetchPairs('id');
foreach ($pole as $id => $data) {
if (!isset($entita[$id])){
$entita[$id] = (new Entita)->id = $id;
}
$entita[$id]->prop1= $data->blabla;
$entita[$id]->prop2= $data->bleble;
$this->orm->persist($entita[$id]);
}
$this->orm->flush();
pokud proeperty budou stejny tak se neprovede nic.
Pokud nejaka hodnota bude jina provede se update.
A samozrejme pokud entita neni vytvori nova, se tudiz se provede Insert.
Jde mi o te ze kdyz parsuji Xml kde mam hodne dat a chci to pak ukladat do databaze abych mel co nejmin sql dotazu.
Editoval tomasde (2. 2. 22:53)
- Marek Bartoš
- Nette Blogger | 1309
Takto jsem to kdysi řešil já
public function __set(string $name, mixed $value): void
{
if (!$this->hasValue($name) || $this->getValue($name) !== $value) {
$this->setValue($name, $value);
}
}