Nette Framework
  • Úvodní stránka
  • Download
  • Dokumentace
  • Fórum
  • Blog
  • Přispějte
  • Quick Start
    • Začínáme
    • Adresářová struktura
    • Vytvoření presenteru
    • Připojení šablony
    • Tvorba odkazů
    • Hezčí šablony
    • Zobrazení tabulky
    • Stránkování a řazení
    • Tvoříme komponentu
  • Nette\Application
    • Application
    • AppForm
    • Control
    • Presenter
    • PresenterCompo­nent
    • PresenterRequest
    • MultiRouter
    • Route
    • SimpleRouter
  • Nette\Caching
  • Nette\Component
  • Nette\Debug
    • Základy
    • Logování chyb
    • Firebug
  • Nette\Environment
  • Nette\Forms
  • Nette\IO\SafeS­tream
  • Nette\Loaders
  • Nette\Object
  • Nette\Security
    • Bezpečnost aplikací
    • Identity
    • SimpleAuthenti­cator
    • Permission
    • Dynamická správa rolí a zdrojů
  • Nette\String
  • Nette\Templates
    • Template
    • Template Filters
    • Template Helpers
  • Nette\Web\Html
  • Nette\Web\HttpR­equest
  • Nette\Web\HttpR­esponse
  • Nette\Web\Session
  • Nette\Web\User
Naposledy změněno 16. 11. 2008 Edituj Historie Poslední změny

Nette Framework Quick Start VIII.

Při mnoha záznamech v databázi nám současná podoba aplikace vypíše na jednu stránku všechny záznamy z tabulky. To nebývá ani praktické, ani hezké. A když už jsme v těch úpravách, pohrajeme si také trochu s rozdělením kódu do různých presenterů.

Proč? Důvodem je snaha o přehlednost. Můžeme mít veškerý kód ve výchozím presenteru, ale s rostoucími požadavky na funkčnost aplikace bude výchozí presenter nabývat na rozsáhlosti a – začne se stávat nepřehledným. My si do budoucna ulehčíme práci a vytvoříme si dva nové presentery, BasePresenter.php a TablePresenter.php.

Presenter BasePresenter.php nám zajistí připojení k databázi a nastavení základního filtru pro šablony. Jeho kód tedy bude vypadat takto:

<?php

class BasePresenter extends /*Nette::Application::*/Presenter
{
    /** @var DibiConnection */
    protected $db;

    protected function startup()
    {
        // připojíme se k souboru s databází
        require_once LIBS_DIR . '/dibi/dibi.php';

        $this->db = new DibiConnection(array(
            'driver' => 'sqlite',
            'database' => APP_DIR . '/models/sample.sdb',
        ));
    }

    protected function beforeRender()
    {
        $this->template->registerFilter(/*Nette::Templates::*/'TemplateFilters::curlyBrackets');
    }
}

Heuréka. Právě jsme objevili znovupoužitelnost kódu. Každý presenter, v kterém chceme využívat služeb databáze a filtru TemplateFilter::curlyBrackets, musí splnit jedinou věc – být potomkem presenteru BasePresenter.php.

Jako první změníme podobu našeho výchozího presenteru DefaultPresenter.php. Bude potomkem základního presenteru a bude mít na starosti jedinou věc – vypsat seznam všech tabulek v databázi. Výsledný kód:

<?php

require_once dirname(__FILE__) . '/BasePresenter.php';

class DefaultPresenter extends BasePresenter
{
    public function renderDefault()
    {
        $this->template->tables = $this->db->getDatabaseInfo()->getTableNames();
    }
}

Nyní zbývá vylepšit a usnadnit práci se zobrazenými záznamy tabulky.

Stránkování a řazení podle sloupců

Všechen kód, mající na starost zobrazení záznamů, umístíme do presenteru TablePresenter.php. Nahlédnutím do kódu zjistíte, že přibyla funkce stránkování a řazení podle sloupců.

<?php

require_once dirname(__FILE__) . '/BasePresenter.php';

class TablePresenter extends BasePresenter
{
    /** @persistent */
    public $page = 0;

    /** @persistent */
    public $order = '';


    public function renderDefault($table, $orderBy)
    {
        // sorting
        parse_str($this->order, $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, '', '&');

        // paging
        $rowsPerPage = 15;
        $numOfRows = $this->db->select('count(*)')->from($table)->fetchSingle();
        $numOfPages = (int) ceil($numOfRows / $rowsPerPage);
        $this->page = max(0, min($this->page, $numOfPages - 1));

        // paginator
        if ($numOfPages > 1) {
            $steps = range(max(0, $this->page - 3), min($numOfPages - 1, $this->page + 3));
            $steps = array_merge($steps, range(0, $numOfPages - 1, (int) ceil($numOfPages / 5)));
            $steps[] = $numOfPages - 1;
            sort($steps);
            $steps = array_unique($steps);
        } else {
            $steps = array();
        }

        // retrieving data
        $query = $this->db->select('*')
            ->from($table)
            ->offset($this->page * $rowsPerPage)
            ->limit($rowsPerPage);

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

        $rowset = $query->execute();

        $this->template->table = $table;
        $this->template->order = $list;
        $this->template->currentOrder = $this->order;
        $this->template->currentPage = $this->page;
        $this->template->numOfPages = $numOfPages;
        $this->template->steps = $steps;
        $this->template->rows = $rowset->fetchAll();
        $this->template->columns = $rowset->getColumnNames();
    }

}

Úprava šablon

Nyní je na čase vytvořit šablonu, která se nám postará o zobrazení záznamů z tabulky. Názvy sloupců jsou aktivní a zpřístupňují řazení. Obsah šablony Table.default.phtml je následující:

<h2>Table „{$table}“</h2>

<p><a href="{plink Default:}">Return to home</a></p>

{if $numOfPages > 1}
<div class="paginator">
    {if $currentPage > 0}
    <a href="{link this, $table, 'page' => $currentPage - 1}">« Previous</a>
    {else}
    <span class="button">« Previous</span>
    {/if}

    {foreach $steps as $num}
    {if isset($lastNum) && $num - $lastNum > 1}<span>…</span>{/if}
    {if $num == $currentPage}
        <span class="current">{$num + 1}</span>
    {else}
        <a href="{link this, $table, 'page' => $num}">{$num + 1}</a>
    {/if}
    {? $lastNum = $num }
    {/foreach}

    {if $currentPage < $numOfPages - 1}
    <a href="{link this, $table, 'page' => $currentPage + 1}">Next »</a>
    {else}
    <span class="button">Next »</span>
    {/if}
</div>
{/if}


<table class="grid" border="1">
<tr>
    {foreach $columns as $column}
    <th><a href="{link this, $table, $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{!$num % 2 ? ' class="alt"' : ''}>

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

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

Původní šablonu Default.table.phtml nyní můžeme vymazat. Nesmíme zapomenout na jednu důležitou věc – v seznamu tabulek z databáze se odkazujeme na neexistující pohled Table. Musíme tento odkaz upravit na nově vytvořený presenter Table.

<h2>Tables:</h2>
<ul>
    {foreach $tables as $table}
    <li><a href="{plink Table: $table}">{$table}</a></li>
    {/foreach}
<ul>

Rozdíl nemusí být na první pohled patrný. Odpovědí je dvojtečka!

Nyní máme vytvořenu základní kostru aplikace, včetně inteligentního zobrazní dat. Co nyní? Rozvineme trochu znovupoužitelnost kódu a ukážeme si, jakým způsobem vytvořit komponentu.

Aplikaci si můžete opět stáhnout.

« Zobrazení tabulky Tvoříme komponentu »

Nette Framework powered | dibi powered | Texy! powered | Institut Školení PHP