SQL Dotaz na vice tabulek v šabloně
- fejtis
- Člen | 16
Omlouvám se za tento, pro vás asi směšný dotaz, ale nikde na fóru jsem
na to nic nenašel.
Jde mi o vypisování (např. kategorií a subkategorií) na jednom místě
stránek.
Mám vytvořený model pro kategorie:
namespace Model;
use dibi;
class Category extends BaseModel {
public static function getAllCategories(){
return dibi::fetchAll('SELECT * FROM [categories], [subcategories]
WHERE [categories.id] = [subcategories.category_id]
GROUP BY [categories.category] ORDER BY
[categories.category], [subcategories.subcategory] ', dibi::DESC);
}
}
V BasePresenteru si potom předám proměnnou s načteným polem do view. Ale ve view nevím jak obsah zobrazit. Potřebuju něco ve smyslu:
{foreach $categories as $cat}
{$cat[‚category‘]}
// zde vypsat dané subkategorie ke kategorii
{/foreach}
A na závěr: Je něco špatně na tom, že tento kód je přímo v layoutu? Nemělo by to být oddělené? Je vhodné cashování tohoto bloku z hlediska zrychlení?
Moc děkuji
Editoval fejtis (16. 2. 2011 21:38)
- Šaman
- Člen | 2668
Není to špatně. Zobrazovací logika patří do View (tedy i to, že mám zobrazit každý prvek pole), proto tam ta makra jsou. Špatné by bylo, kdybys ten SQL dotaz měl v šabloně.
Co se cachování týče: záleží na tom, jaká data taháš. Ale obecně se optimalizuje až když zjistíš, že je to potřeba.
- fejtis
- Člen | 16
Díky za postřehy.
Problém jsem vyřešil v šabloně takto
{foreach $categories as $cat}
<optgroup label="{$cat['category']}">
{foreach Model\Category::getSubcategories($cat['id']) as $subcat}
<option value="{$subcat['id']}">{$subcat['subcategory']}</option>
{/foreach}
</optgroup>
{/foreach}
- Šaman
- Člen | 2668
Aha, teď jsem teprve pochopil v čem je háček. To volání
Model\Category::getSubcategories
by ve VIEW asi být nemělo.
Ideální by bylo kdyby objekt kategorie už měl v sobě podkategorie a pak by
stačilo procházet přímo ten objekt. Prostě jen zobrazit co dodal presenter,
ne ještě načítat něco nového.
Čistější by bylo, pokud bys nevolal statickou metodu, ale
$cat->getSubcategories()
, resp. dá se to zkrátit i na
$cat->subcategories
(pokud Model dědíš od Nette\Object).
- Filip Procházka
- Moderator | 4668
namespace Model;
use dibi;
class Category extends BaseModel
{
public static function getAllCategories()
{
$categories = dibi::select('*')
->from('categories')
->orderBy(array('category' => dibi::DESC))
->fetchAssoc('id');
$subcategories = dibi::select('*')
->from('subcategories')
->orderBy(array('subcategory' => dibi::DESC))
->where('category_id IN %l', array_keys($categories))
->fetchAssoc('category[]->');
foreach ($categories as $id => &$category) {
$category['sub'] = $subcategories[$id];
}
return $categories;
}
}
no a vypíšeš to následovně
{foreach $categories as $cat}
<optgroup label="{$cat['category']}" n:inner-foreach="$cat['sub'] as $subcat">
<option value="{$subcat['id']}">{$subcat['subcategory']}</option>
</optgroup>
{/foreach}
Ale pokud to chceš použít ve formulářích.
namespace Model;
use dibi;
class Category extends BaseModel
{
public static function getAllCategories()
{
$categories = dibi::select('id,category')
->from('categories')
->orderBy(array('category' => dibi::DESC))
->fetchPairs();
$subcategories = dibi::select('id,subcategory')
->from('subcategories')
->orderBy(array('subcategory' => dibi::DESC))
->where('category_id IN %l', array_keys($categories))
->fetchAssoc('category_id[]->');
$options = array();
foreach ($categories as $id => $category) {
$options[$category] = $subcategories[$id];
}
return $options;
}
}
A pak jednoduše
$form = new Nette\Application\AppForm();
// ...
$form->addSelect('category', 'Kategorie', Category::getAllCategories());
//...