Vytváření různých šablon pro jednu komponentu

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
vymak
Člen | 92
+
0
-

Ahoj chtěl bych se zeptat jaký je správný postup při vytváření různých šablon v jedné komponentě. Nyní to mám navrhnuté takhle:

BaseControl:

class BaseControl extends Control
{

	private $name;

	public function setName($name)
    {
        if (!$name) {
            $this->name = NULL;
            return;
        }

        if ($name === 'render') {
            return;
        }

        $replaced = Strings::replace($name, '/render/');
        $this->name = $replaced;
    }

	/**
     * @return ITemplate
     */
    protected function render()
    {
        $class = new ClassType($this);
        $path = $class->shortName;
        $path[0] = Strings::lower($path[0]);

        $dir = '';
        if ($class->inNamespace()) {
            $dir = $class->namespaceName . '/';
        }

        $template = $this->template;
        $template->setFile(APP_DIR . '/components/templates/' . Strings::webalize($dir, '/') . Strings::replace($path, '/Control/') . $this->name . '.latte');
        return $template;
    }

V případě že je v komponentě pouze klasická metoda render() vše funguje bez problémů. Jakmile chci ale použít například ještě renderOther() řeším to takhle:

class PartnersControl extends BaseControl implements IComponent
{

    public function render()
    {
        $this->name = NULL;
        $template = parent::render();
        $template->render();
    }

    public function renderOther()
    {
        $this->name = __FUNCTION__;
        $template = parent::render();
        $template->render();
    }

}

Takhle to sice funguje, ale pokud se render volá až pod renderOther použije se nastavený

$this->name

Musím jej tedy v klasické metodě render smazat. Napadlo mě řešení, že by se v mé třídě BaseControl v metodě render zjišťovalo jaká metoda jej zavolala, ale netuším jestli je to z technického hlediska vůbec možné.

Tedy něco jako:

class BaseControl extends Control
{

	private function returnName($name)
    {
        $replaced = Strings::replace($name, '/render/');
		return $replaced;
    }

	/**
     * @return ITemplate
     */
    protected function render()
    {
		$methodWhichCall = get_method_which_call_this(); // tady tohle právě nevím zdali nějak lze

		$name = $this->returnName($methodWhichCall);
        $class = new ClassType($this);
        $path = $class->shortName;
        $path[0] = Strings::lower($path[0]);

        $dir = '';
        if ($class->inNamespace()) {
            $dir = $class->namespaceName . '/';
        }

        $template = $this->template;
        $template->setFile(APP_DIR . '/components/templates/' . Strings::webalize($dir, '/') . Strings::replace($path, '/Control/') . $name . '.latte');
        return $template;
    }
Šaman
Člen | 2666
+
0
-

Tohle není dobré. Metoda render() má za úkol vykreslit pohled (klidně echem), nikoliv vrátit šablonu. Jestli ti jde o to, abys nemusel pokaždé nastavovat soubor šablony, vytvoř si na to vlastní metodu a tu pak volej, nebo nevolej, jak budeš potřebovat. Ale bude to průhledné a srozumitelné.
Už jsem to řešil, měl jsem i podobná řešení, jako ty (až na to, že render pokaždé vykresloval, nic nevracel), ale zatím nejsrozumitelnější mi přišlo tohle

Ty jiné pohledy nejsou vůbec běžné, takže při tvorbě nového pohledu s vlastní šablonou už ten jeden řádek $template->setFile(__DIR__ . '/foo.latte'); moc nezdrží a čitelnost výrazně zlepší. Render metoda hledá soubor podle konvence, ostatní to musí specifikovat explicitně (a i ta render se dá přepsat na jiný soubor explicitně).

Editoval Šaman (14. 9. 2014 17:08)