Přepis MySQL dotazu do Nette Database Explorer
- cafesk8
- Člen | 103
Zdravím,
mám SQL dotaz pro hledání nejbližších lokací v tabulce pro zadané GPS souřadnice. Funguje to jak má:
<?php
$vysledek = $this->db->query('
SELECT id, lat, lng, address,
111.045
* DEGREES(ACOS(COS(RADIANS(latpoint))
* COS(RADIANS(lat))
* COS(RADIANS(longpoint) - RADIANS(lng))
+ SIN(RADIANS(latpoint))
* SIN(RADIANS(lat)))) AS distance_in_km
FROM advert
JOIN (
SELECT '.$lat.' AS latpoint, '.$lng.' AS longpoint
) AS p ON 1=1
#HAVING distance_in_km < 10
ORDER BY distance_in_km
LIMIT 15'
);
?>
Avšak rád bych si to nějak přepsal do Database Exploreru něco jako:
<?php
$vysledek = $this->db->table('advert')->where(/* zde nějak přepsat ten výpočet s JOIN apod.? */)->limit(15);
?>
Jde mi o to, abych výsledky měl spíše jako objekty, mám pak různé tabulky s daty o lokacích propojené přes ID v této tabulce a rád bych pak v šabloně volal něco jako
<?php
{foreach $vysledek->related('advert_property') as $lokace}
{$lokace}
{/foreach}
?>
Nevím jestli jsem se správně vyjádřil, nebo zda to je správný postup, ale ocením každý tip a radu.
Díky
- Ondřej Kubíček
- Člen | 494
klidně to můžeš nechat takhle, šak to query vrací
ResultSet
, na kterým zavoláš třeba fetchAll()
a to
vrátí pole ActiveRow
, kde si můžeš volat related
,
nebo to ti ted nejde? co to teda vrací?
- cafesk8
- Člen | 103
Šablona
<?php
foreach $vysledek as $v}
{dump $v}
{/foreach}
?>
Vrací instance Nette\Database\Row
namísto
ActiveRow
a potom tedy, když si zavolám
<?php
{foreach $vysledek as $v}
{foreach $v->related('advert_meta') as $meta}
{dump $meta}
{/foreach}
{/foreach}
?>
Tak to logicky řve Call to undefined method Nette\Database\Row::related()
V presenteru to mám takto:
<?php
$vysledek = $this->db->query('
SELECT id, lat, lng, address,
111.045
* DEGREES(ACOS(COS(RADIANS(latpoint))
* COS(RADIANS(lat))
* COS(RADIANS(longpoint) - RADIANS(lng))
+ SIN(RADIANS(latpoint))
* SIN(RADIANS(lat)))) AS distance_in_km
FROM advert
JOIN (
SELECT '.$lat.' AS latpoint, '.$lng.' AS longpoint
) AS p ON 1=1
#HAVING distance_in_km < 10
ORDER BY distance_in_km
LIMIT 15'
)->fetchAll();
$this->template->vysledek = $vysledek;
?>
- Ondřej Kubíček
- Člen | 494
hmm tak sorry, ono to fakt vrací jen Row, ne ActiveRow, jak jsem původně myslel
- Šaman
- Člen | 2664
Protože voláš fetchAll()
dvakrát. Jednou, než vrátíš
výsledek (takže vracíš již pole) a podruhé v tom foreach. V tom
presenteru to fetchAll
smaž.
//edit: vlastně můžeš smazat kterýkoliv, ale obecně se doporučuje držet objekt až do poslední chvíle před vykreslením. Protože na té query můžeš ještě dodatečně chtít nějaké limity, offsety, nebo řazení (typicky kvůli stránkování).
Editoval Šaman (20. 7. 2018 12:45)
- cafesk8
- Člen | 103
Šaman napsal(a):
Protože voláš
fetchAll()
dvakrát. Jednou, než vrátíš výsledek (takže vracíš již pole) a podruhé v tom foreach. V tom presenteru tofetchAll
smaž.//edit: vlastně můžeš smazat kterýkoliv, ale obecně se doporučuje držet objekt až do poslední chvíle před vykreslením. Protože na té query můžeš ještě dodatečně chtít nějaké limity, offsety, nebo řazení (typicky kvůli stránkování).
Já to původně v tom presenteru neměl, respektive vždy jsem to volal
jenom jednou, ale ať dám to fetchAll()
v presenteru nebo
v šabloně, tak to vrací Row
namísto ActiveRow
.
Problém je, že na Row
nemůžu volat ve smyčce
<?php
$v->related('neco');
?>
Skončím, tam kde jsem začal, tudíž Call to undefined method Nette\Database\Row::related()
- norbe
- Backer | 405
Že jsem tak smělý, jaký význam má ten join kde si vybereš akorát statické hodnoty? Proč je nepoužiješ rovnou v tom výpočtu?
Tedy cca takto:
$this->db->table('advert')
->select('id, lat, lng, address,
111.045
* DEGREES(ACOS(COS(RADIANS(?))
* COS(RADIANS(lat))
* COS(RADIANS(?) - RADIANS(lng))
+ SIN(RADIANS(?))
* SIN(RADIANS(lat)))) AS distance_in_km', $lat, $lng, $lat)
->order('distance_in_km')
->fetchAll()
- cafesk8
- Člen | 103
norbe napsal(a):
Že jsem tak smělý, jaký význam má ten join kde si vybereš akorát statické hodnoty? Proč je nepoužiješ rovnou v tom výpočtu?
Tedy cca takto:
$this->db->table('advert') ->select('id, lat, lng, address, 111.045 * DEGREES(ACOS(COS(RADIANS(?)) * COS(RADIANS(lat)) * COS(RADIANS(?) - RADIANS(lng)) + SIN(RADIANS(?)) * SIN(RADIANS(lat)))) AS distance_in_km', $lat, $lng, $lat) ->order('distance_in_km') ->fetchAll()
Super, po pravdě jsem ten dotaz celý zkopíroval, takže mi nedošlo, že to tam je zbytečně. Takto to funguje, díky moc!
Editoval cafesk8 (20. 7. 2018 15:01)