Jak na rekurzi v šabloně aneb jak vykreslit rodokmen?
- Croc
- Člen | 270
Zdravím,
aktuálně jsem narazil na problém s vykreslením rodokmenu v šabloně.
Rodokmen mám aktuálně řešen čistě v PHP (z dávných časů) a teď ho chci překlopit do Nette. Princip generování rodokmenu mám následující:
function rodokmen ($zvire,$hloubka) {
// zde se provede dotaz na načtení údajů a rodičů pro $zvire z DB
//data se nacetli z DB jdeme na to je zpracovat
while ($Vysledek = $stmt->fetch()) {
// zde se provede vykreslení údajů zvířete (jako jedna položka v rodokmenu) a probíhá práce s promenou $hloubka
//tady je rekurze!
rodokmen ($Vysledek['matka'],$hloubka);
rodokmen ($Vysledek['otec'],$hloubka);
}
}
Uvedený princip bych tedy potřeboval překlopit do Nette, ale nevím jak modelovou metodu průběžně vykreslovat přes presenter do šablony.
Nevíte někdo jak na to prosím? Díky moc
Editoval Croc (25. 10. 2015 8:53)
- Azathoth
- Člen | 495
já když jsem potřeboval vykreslovat strom, tak jsem měl komponentu na
vykreslení jednoho vrcholu a v cyklu jsem pak vypsal komponentu pro každého
potomka.
Takže komponenta Node má v sobě tohle latte
<li>
{*dome data about node*}
<ul n:if="count($descendants) > 0">
{foreach $descendants as $descendant}
{control node-$descendant->id}
{/foreach}
</ul>
</li>
a v ta komponenta tedy, jak vidíš, dostane ID toho vrcholu, podle toho má
vrchol, který má vypsat a v proměnné descendants má všechny potomky toho
vrcholu.
Takže z modelu se vytáhne vždycky vrchol + jeho potomci. A takhle se to
provede pro každý vrchol stromu.
Editoval Azathoth (25. 10. 2015 10:23)
- Croc
- Člen | 270
Nevím jestli dělám něco špatně, ale nějak se mi to nedaří rozchodit.
Mám vytvořenou komponentu:
EDIT:
INodeFactory.php
namespace App\Components;
interface INodeFactory
{
/**
* @return NodeControl
*/
public function create();
}
NodeControl.php
namespace App\Components;
use Nette\Application\UI\Control;
class NodeControl extends Control
{
/** @var \Nette\Database\Context */
private $database;
/** @var \App\Repository\AnimalRepository */
protected $animalRepository;
private $parents;
private $animal;
public function __construct(\App\Repository\AnimalRepository $animalRepository) {
parent::__construct();
$this->animalRepository = $animalRepository;
}
protected function createComponentNode()
{ $animalRepository = $this->animalRepository;
$node = new Components\NodeControl($animalRepository);
return $node;
}
public function render($id)
{
$template = $this->template;
$template->setFile(__DIR__ . '/NodeControl.latte');
$this->template->animal = $this->animalRepository->getAnimal($id);
$this->template->parents = $this->animalRepository->getAnimalParents($id);
$template->render();
}
}
NodeControl.latte
{block node}
{foreach $parents as $parent}
{if $hloubka <> 5} //vykreslení části tabulky dle její hloubky
{if $hloubka == 4} <tr><td rowspan="8"> {/if}
{if $hloubka == 3} <td rowspan="4"> {/if}
{if $hloubka == 2} <td rowspan="2"> {/if}
{if $hloubka == 1} <td> {/if}
{if $hloubka > 0}
{$animal->name} </td> //jméno zvířete
{/if}
{/if}
{if $hloubka == 1} </tr> {/if}
{if $hloubka <= 0}
{php return}
{else}
{php $hloubka--}
{control node, $parent->id_father, $hloubka}
{control node, $parent->id_mother, $hloubka}
{/if}
{/foreach}
{/block}
V šabloně kde chci strom vykreslit mám toto:
{block content}
{control node, $animal->id_animal}
{/block}
Problém je, že mi Tracy hlásí chybu
Component with name 'node' does not exist.
v šablone
NodeControl.latte právě při volání rekurze.
Nevíte prosím co tam mám špatně?
Editoval Croc (25. 10. 2015 22:35)
- Šaman
- Člen | 2640
Vždyť v kódu komponenty opravdu žádnou továrnu na komponentu
Node
nemáš (createComponentNode()
).
Jinak já jsem tohle řešil v šabloně bez komponenty, jen jsem includoval latte blok. A jako parametr dostal celý objekt uzel, nikoliv jeho id. Pro větší stromy to bude i citelně efektivnější, než pro každý uzel znovu sahat do repozitáře.
- Croc
- Člen | 270
@Šaman Díky, měl si pravdu :)
@Azathoth Doctrine nepoužívám, takže to musím načítat z DB po jednom. Třeba časem k tomu dojde :)
Ještě potřebuju vyřešit jednu drobnost a tou je hloubka vykreslení
rodokmenu jako vstupní parametr. Logiku vykreslení jsem použil
z předchozího webu (non-Nette) a při každé rekurzi předávám parametr
$hloubka
(aby to nevykreslovalo do nekonečna). Problém mám
v tom, že se mi při rekurzi nedaří ten parametr předat… V postu výše
jsem doplnil aktuální stav.
- Croc
- Člen | 270
Vyřešeno, nakonec jsem měl chybu v datech, rodokmen se mi tedy již vykresluje
@Azathoth Určitě to je lepší řešení jak říkáš. Udělám ještě výkonnostní testy, ale asi to zatím nechám takto. Mám toho ještě dost před sebou co musím řešit takže se k tomu určitě někdy vrátím :)
Díky tedy všem za rady.
Editoval Croc (25. 10. 2015 23:27)