Řazení s persistentním parametrem

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

Ahoj, mám problém s rozchozením řazení tak, jak je popsáno v quick-startu
Možná to není tak docela problém, ale jednoduše nechápu, jak to má fungovat. Pro úplnost přidávám kód, který by ale měl být totožný s quick-startem (je tam nějaká omáčka okolo).

<?php
class Front_GoodsCategoriesPresenter extends Front_DefaultPresenter
{
   /** @persistent */
   public $order = '';

   /**
    * Vypsani kategorie
    * @param string $id link kategorie
    * @param string $orderBy
    * @return void
    * TODO: Tahat data z modelu
    */
   public function renderDefault($id, $orderBy) {
      // pripojit model
      $this->model = new Goods();
      $table = Goods::TABLE;

      // zkusit najit podkategorie, pokud neni zadna, dostali sme se na neexistujici kategorii
      $categories = $this->model->getSubCategories($id);
      if ($categories === false)
         $this->redirect("Front:Special:404");

      parse_str($orderBy, $list);
      if ($orderBy) {
         if (!isset($list[$orderBy])) {
             $list[$orderBy] = 'a';
         } elseif ($list[$orderBy] === 'd') {
             unset($list[$orderBy]);
         } else {
             $list[$orderBy] = 'd';
         }
      }
      $this->order = http_build_query($list, '', '&');

      // strankovani
      $vp = new VisualPaginator($this, 'paginator');
      $paginator = $vp->getPaginator();
      $paginator->itemsPerPage = 5;
      $paginator->itemCount = dibi::fetchSingle("
         SELECT COUNT(*)
         FROM [".$table."]
         WHERE [status]=%s", 'publish', "AND ([category]=".implode(' OR [category]=', $categories), ")");


      // nacteni polozek - fluent
      $query = dibi::select('*')
         ->from($table)
         ->where("[category]=".implode(" OR [category]=", $categories))
         ->offset($paginator->getOffset())
         ->limit($paginator->getLength());

      // nastavit razeni
      $i = 1;
      foreach ($list as $field => $dir) {
         $query->orderBy($field, $dir === 'a' ? 'ASC' : 'DESC');
         $list[$field] = array($dir, $i++);
      }

      // nacist
      $rowset = $query->execute();
      $rows = $rowset->fetchAll();

      // nahradit fnodes obrazku za cesty (nechat pouze jeden obrazek)
      $this->model->imageNodesToPaths(&$rows, $single=true);

      $this->template->id = $id;
      $this->template->order = $list;
      $this->template->paginator = $vp;
      $this->template->rows = $rows;
      $this->template->columns = $rowset->getColumnNames();
      $this->template->currentOrder = $this->order;
   }

}
?>
<?php
<table class="grid" border="1">
<tr>
    {foreach $columns as $column}
    <th><a href="{link this, $id, $column}"
    {if isset($order[$column])} class="{$order[$column][0] === 'a' ? 'asc' : 'desc'}"{/if}
    >{$column}{if count($order) > 1 && isset($order[$column])}&nbsp;<span>{$order[$column][1]}</span>{/if}</a></th>
    {/foreach}
</tr>

{foreach $rows as $num => $row}
<tr{if $iterator->isOdd()} class="alt"{/if}>

    {foreach $row as $value}
    <td>{=substr($value, 0, 100)}</td>
    {/foreach}

</tr>
{/foreach}
</table>

{$paginator->render()}
?>

Řazení se ale chová tak, že řadí pouze podle jednoho sloupce (QS tvrdí něco jiného), a navíc se v adrese (dle mého zbytečně) předávají dva parametry (order a orderBy), které jsou ve výsledku shodné. (Myšleno tak, že link sice odkazuje na adresu s různými parametry, ale pak se to nějak přesměruje a jsou shodné.)

Proč dva parametry? A k čemu má $order a $orderBy sloužit? Když jsem řešil řazení dříve (bez Nette), stačil mi jeden parametr v odkazu, což by tady mohlo být ono $orderBy, které se z linku předá presenteru. K čemu je potom druhý, persistentní parametr?

Opravdu bych ocenil, kdyby mi někdo alespoň zjednodušeně popsal tok dat. Sedím nad tím už pár hodin, nic kloudného jsem nevymyslel, a přijde mi, že čím déle to řeším, tím méně tomu kódu rozumím :( (A to QS ještě tvrdí K pochopení tohoto mechanismu opět napomůže nahlédnout do zdrojového kódu.)

jasir
Člen | 746
+
0
-

na1k napsal(a):

V rychlosti:

  • $order je persistentní proměnná presenteru, která si udržuje pole (ve tvaru query stringu) sloupců podle kterých se sortuje
  • $orderBy je parametr metody renderDefault() a potažmo linku z hlavičky tabulky, takže když uživatel klikne na jméno sloupce, jméno tohoto sloupce přijde do renderDefault() jako parametr

Zde máš chybu (plynoucí zřejmě z výše uvedeného nepochopení):

<?php
      parse_str($orderBy, $list);
      if ($orderBy) {
         if (!isset($list[$orderBy])) {
             $list[$orderBy] = 'a';
         } elseif ($list[$orderBy] === 'd') {
             unset($list[$orderBy]);
         } else {
             $list[$orderBy] = 'd';
         }
      }
?>

protože by to mělo být nějak jako:

<?php
      parse_str($this->order, $list); //vyrob z persistentní proměnné order array
      if ($orderBy) {
         if (!isset($list[$orderBy])) {
             $list[$orderBy] = 'a';
         } elseif ($list[$orderBy] === 'd') {
             unset($list[$orderBy]);
         } else {
             $list[$orderBy] = 'd';
         }
      }
      $this->order = http_build_query($list, '', '&');
?>

Editoval jasir (17. 7. 2009 17:12)

na1k
Člen | 288
+
0
-

Skvělé, moc díky!

Já jsem to právě zkopíroval z quickstartu a vůbec sem nechápal. Teď už je to tam opravené a po tvém vysvětlení to dává smysl a vlastně to není ani tak složité :-) Tak ještě jednou dík.