Princip operování nad výsledky z databáze?

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

Zdravím Vás,

jsem teprve začátečník v oblasti MVC modelu a přemýšlím nadtím jak řešit jednoduchý problém – operaci nad výsledky z databáze. Uvedu na příkladu:

Model

<?php
class ArticleModel extends BaseModel
{
   public function getArticles($id)
   {
      return dibi::select("*")->from("[:prefix:articles]")->fetchAll();
   }
}
?>

Presenter

<?php
class ArticlePresenter extends BasePresenter
{
   public function actionDefault()
   {
      $art = new ArticleModel;
      $this->template["articles"] = $art->getArticles();
   }
}
?>

Template

<ul>
{foreach $articles as $article}
   <li>{$article->rank}</li>
{/foreach}
</ul>

V presenteru tedy se připojít do modelu a přijmu data, která potřebuji a předám je do templatu, kde je projdu cyklem a vypíšu.

Co, když ale budu chtít vrácený sloupec rank upravit nějakou funkcí (umocnit/odmocnit/atd) – ano mnohé věci se dají aplikovat na přímo na SELECT, nebo přes Helpery, ale když to bude složitější operace, tak jak to lze udělat aniž bych musel procházet pole s výsledky dvakrát (jednou v presenteru a potom znovu v šabloně)? Či jak se toto řeší?

Víceméně jako když bez tohoto MCV modelu čistě přes PHP uděláte:

<?php
$articles = dibi::select("*")->from("[:prefix:articles]")->fetchAll();
echo "<ul>";
foreach ($articles as $article) {
   $article["rank"] = // ... nějaké operace s výsledky ...
   echo "<li>{$article["rank"]}</li>";
}
echo "</ul>;
?>

BTW: Případně ještě dodatek, pouze mi není ještě přímo jasná věc, co by se mělo provádět v render a co v action, (ale to není tak důležité jako předchozí otázka) .. všiml jsem si, že tedy action přijímá jak parametry, tak může pracovat se statickýmí třídami (oproti render) a může i odesílat do template, takže render bych víceméně vůbec nevyužil !?

Editoval frosty22 (4. 4. 2010 15:57)

Vyki
Člen | 388
+
0
-

Tohle, přesně jak už jsi napsal, lze řešit helperem. Aby jsi nemusel pole procházet 2× a výsledek měnil při cyklu v šabloně, tak by asi helper byl nejčistším řešením. Zajímavé řešení poskytuje Ormion. Tam jsou nastavovat přímo vstupní a výstupní filtry. Také si tam v podstatě registruješ callback, který ti při výběru, insertu, updatu s daty provede nějakou operaci.

Editoval Vyki (4. 4. 2010 16:00)

frosty22
Člen | 373
+
0
-

A to jsem si říkal, že na to bude nějaký triviální způsob na předávání cyklu mezi presenterem a template, takže budu vypadat za blbce :) Pouze mi právě nesedí způsob operovat se sloupci na úrovni šablony.

Například když mám v tabulce celkové hodnocení + kolik lidí hodnotilo a vypočítat výsledek a zaokrouhlit ⇒ jasně můžu přes SELECT dotaz udělat něco jako SELECT hodnoceni/hodnotilo as vysledek .. a potom si zaregistrovat do Helperu fci floor a v šabloně vyvolat .. ale to se mi zdá, že je moc krokolomné..

Ale zkusím tedy onen Ormion ..

redhead
Člen | 1313
+
0
-

Ono Ormion dozajista operuje nad výsledkem také přes cyklus, čili pokud si to v presenteru projedeš svým vlastním foreachem, tak v tom nebude rozdíl..

Vyki
Člen | 388
+
0
-

To záleží co je prioritou. Můžeš to pole projít 2× a data si v poli, které jsi z DB vybral upravit a potom v dalším cyklu šablony vypsat. Způsobů jak to udělat na jeden cyklus by se dalo najít více, ale dělat to jinde než v cyklu výpisu by asi nebylo moc čisté. Bez nutnosti registrovat helper by mohlo šlapat toto:

<?php
class MyPresenter
{
	public function renderDefault()
	{
		$data = dibi::select('SELECT * FROM [tabulka]')->fetchAll();
		$this->template->data = $data;
	}

	public function prumer($a, $b)
	{
		return ($a+$b)/2;
	}
}
?>
{foreach $data as $item}
	<p>Průměr: {$presenter->prumer($item['a'], $item['a'])}</p>
{/foreach}

Netestoval jsem to ale něco v tomto smyslu by šlapat mohlo.