Presenter – rozbor, názorná ukázka chyb

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

Ahoj, byl by tu někdo ochotný mi rozebrat kousek mého presenteru? co se týče Nette a MVP je to úplně první co pomocí toho dělám, a tak mě napadlo že názorná ukázka co jsem udělal špatně by mohla pomoct :-)
zveřejňuji jen ovládání jedné šablony – aby to nebylo pracné se prodírat kodem. děkuju…

<?php

final class ContentPresenter extends Presenter {

    public function actionDefault($menuItem = "uvod") {
        $this->template->description =
			$this->model->getDescription($menuItem);

        if($menuItem == "fotogalerie") {
            $categoriesBuffer = $this->model->getCategories(0);
            $this->template->headerOfCategories = "Fotogalerie";
        } else {
            $categoriesBuffer = $this->model->getCategories();
            $this->template->headerOfCategories = "Nabídka služeb";
        }

        $this->template->categories = $categoriesBuffer;

        $this->template->numInColumns =
		$this->getNumOfRecordsInColumns(count($categoriesBuffer));
    }

    public function renderDefault() {

    }

/**
* Tato funkce mi podle počtu záznamů řekne, kolik záznamů náleži do
* kterého ze tří sloupců... Aby bylo jasno, vždy se nejprve vykresluje
* sloupec 1, pak 2, a pak 3... Takže mám-li např 5 vrácených záznamů,
* pomocí tohoto pole předám šabloně informaci, že první a druhý sloupec
* se má vykreslit se dvěmi záznamy a 3.sloupec s jedním...
**/

    private function getNumOfRecordsInColumns($countOfRecords) {
        $num = $countOfRecords/3;
        $numOfCategoriesInColumns[0] = (integer)$num;
        $numOfCategoriesInColumns[1] = (integer)$num;
        $numOfCategoriesInColumns[2] = (integer)$num;
        $border = (integer)($countOfRecords-(3*((integer)$num)));
        for($i=0; $i<$border; $i++) {
            $numOfCategoriesInColumns[$i]++;
        }
        return $numOfCategoriesInColumns;
    }

}

?>

edit: jen úprava aby se kód nemusel rolovat do strany…

Editoval Ofi (4. 9. 2010 21:40)

Ofi
Člen | 13
+
0
-

No mě třeba zajímalo, jestli jsem správně udělal metodu action, jestli je normální že render zůstal prázdný nebo jestli tam patřilo něco co nemá být v action…

zarubik
Člen | 31
+
0
-

Podle mě by jsi mel mít všechno v render.
Do action patří přesměrování, zobrazení jiného renderu apod.

Ofi
Člen | 13
+
0
-

aha, no já myslel že odesílání dat šabloně patří do renderu, ale zase s modelem by měl manipulovat action nikoliv render ne?

westrem
Člen | 398
+
0
-

No na vysvetlenie co robit kde a ako pouzivat Render a Action doporucujem poriadne precitat nasledovne

K tvojmu kodu, naozaj by dane veci kludne mohli ist do Render metody. Celkovo by to slo trochu aj zjednodusit, ale kazdy mame svoj coding style a nechcem rypat do toho tvojho len preto, ze ja by som to napisal trosilinku odlisne.

Nechapem tak trochu tej metode getNumOfRecordsInColumns – teda chapem co robim, ale nedalo by sa vyuzit toto: Grid renderind ? Resp. pride mi, ze to co robis tou metodou je uz naozaj starost view, presenter by nemal apriori vediet, ze chces v sablone nieco delit do 3 stlpcov a pomahat jej s tym, on jej ma len predat data a ona si ich sama spracuje. Kebyze casom prides na to, ze potrebujes 4 stlpce, musis hned prepisovat aj presenter, pricom za pouzitia Grid renderingu len jedno cislo v template.

Ofi
Člen | 13
+
0
-

Nechapem tak trochu tej metode getNumOfRecordsInColumns – teda chapem co robim, ale nedalo by sa vyuzit toto: Grid renderind ?

no, jak jsem říkal, s nette začínám.. o tomto jsem nevěděl – super tip! díky
aj máš pravdu, mělo by to být ve view, já to bral tak, že to je jako příprava dat než je předá view…

díky za názor, byl přínosný :)

Editoval Ofi (5. 9. 2010 19:00)

Ani
Člen | 226
+
0
-

Osobně si myslím, že:

  1. úvod, fotogalerie a nabídka služeb by měli mít každá svůj view.
  2. to co dělá metoda getNumOfRecordsInColumns by se asi mělo dělat v šabloně, případně rovnou v modelu.
  3. rozlišovat jaké kategorie menu ti vrátí getCategories z modelu, takhle natvrdo podle parametru 0 nebo nic, no nevim. Takhle napohled mi to přijde dost neintuitivní, ale když se v tom vyznáš.

Body 2 a 3 nejsou až tak důležité, ale bod jedna by mol znamenat nepochopení základních principů, tak se nad tím zkus zamyslet ;)

Podle toho kousku se to těžko posuzuje.

westrem
Člen | 398
+
0
-

Ofi napsal:

No priprava dat, model sa vecsinou pouziva cisto na ziskavanie RAW dat s tym, ze nejak kanonizuje ich typ a sablona s nimi potom robi co uzna za vhodne, preto existuju helpery a filtre.

Priklad: Z modelu si vytiahnes nejaky datum s casom. V jednej sablone ho budes chciet zobrazit iba ako DD.MM.YYYY kdezto napr. v nejakom admin rozhrani bude pre teba dolezite aj presna minuta a hodina kedy sa akcia udiala tak si to vypises ako DD.MM.YYYY HH:MM:SS. V oboch pripadoch z modelu do sablony predas RAW datum (napr. ako int timestamp alebo DateTime object) a az v sablone si s tym robis upravu na pozadovany format.

Ani napsal:

Wow, nejak som si neuvedomil tu logiku za tym, ale mas pravdu, ak to robi to na co sa to javi, tak fotogalerie, uvod a aj nabidka sluzieb by mali byt separatne views, tzn kazdy z nich by mal mat vlastnu render metodu a vlastnu sablonu :)

Ofi
Člen | 13
+
0
-

Ani napsal(a):

Osobně si myslím, že:

  1. úvod, fotogalerie a nabídka služeb by měli mít každá svůj view.

a není to zbytečné, protože ve všech třech případech je kód šablony stejný, jsou pouze jiná data, která view dostane… proto to mám dohromady a ovládá to ContentPresenter…

  1. to co dělá metoda getNumOfRecordsInColumns by se asi mělo dělat v šabloně, případně rovnou v modelu.

ano ano, souhlasím, jak naznačil kolega nahoře, zbytečně jsem si to zkomplikoval :)

  1. rozlišovat jaké kategorie menu ti vrátí getCategories z modelu, takhle natvrdo podle parametru 0 nebo nic, no nevim. Takhle napohled mi to přijde dost neintuitivní, ale když se v tom vyznáš.

0 = false, 1= true a 1 je implicitně… vzhledem k tomu že ta metoda má jen jeden parametr a že jsem k ní napsal dokumentaci a používám IDE mi to přijde postačující a myslím, že bych to pochopil i za rok :-) možná by bylo lepší tam psát true a false a nenechávat prázdné kvůli rozlišení, na to možná dojde ale až při refaktoringu :-)
>
díky za zhodnocení ;-) co ta 1) i tak by to mělo být oddělené? nevznikne mi tím hodně duplicitního kódu?

Editoval Ofi (6. 9. 2010 16:55)

Ani
Člen | 226
+
0
-

Tak pokuď jsou to čistě obsahové (fotogalerie není fotogolarie, ale jen normální stránka, která se jmenuje fotogalerie) stránky, tak to může být v jednom view.

Jak už jsem psal „Podle toho kousku se to těžko posuzuje.“.

Ofi
Člen | 13
+
0
-

je to v podstatě tak že se pošle šabloně description pro daný menu item a buď všechny položky „nabídka služeb“ (pro úvod a nabídka služeb), nebo fotogalerie (pro fotogalerie) každá stránka pak vypíše nadpis, popis, a stejný formát pro výběr v nabídce služeb nebo fotogalerii… dyžtak postnu i kód šablony :)

{block title}
<title>{$description->menuItem}</title>
{/block}
{block content}


    {if isset($description) && $description != null}
        <h3>
            {$description->menuItem}
        </h3>
        <p>{!$description->description}</p>
    {/if}

{if isset($categories)}
    <hr class="multi-separator">
    <h3>
        {$headerOfCategories}
    </h3>
    <ul>
    {foreach $categories as $key => $value}
        {if $key==0 ||
	    $key==$numInColumns[0] ||
	    $key==$numInColumns[0]+$numInColumns[1]
	}
              <li>
        {else}
              <hr class="separator">
        {/if}
              <strong>
                  <a href="{link detail,
			String::webalize($headerOfCategories),
			$value->seoUrl}">
			{$value->title}
		  </a>
              </strong>
              <img
	src="images/uploaded/{$value->seoUrl}/{$value->firstImage}"
	alt="alt"
	width="170">
    {/foreach}
    </ul><hr class="clear">
{/if}

{/block}