Nette
Database

databázový layer
pro PHP

Database Core

Nette Database Core je základní vrstva pro přístup k databázi, tzv. database abstraction layer. Tvoří obálku nad PDO a poskytuje základní funkcionalitu pokládání dotazů.

Database Explorer

Nette Database Explorer zásadním způsobem zjednodušuje získávání dat z databáze bez nutnosti psát SQL dotazy. Pokládá efektivní dotazy a nepřenáší zbytečná data.

Přes 10 let vývoje

Nette vyvíjíme přes 10 let - a číslo stále roste! Knihovny, které poskytujeme, jsou proto velmi zralé, stabilní a široce používané. Věří jim řada globálních korporací a pohání mnoho významných webových stránek. Kdo používá a důvěřuje Nette?

Databáze & ORM

Nette Framework vám poskytuje vrstvu pro výrazně pohodlnější práci s databázemi. Co umí?

  • snadno skládat SQL dotazy
  • snadno získávat data
  • pokládá efektivní dotazy a nepřenáší zbytečná data

Základem je obálka nad PDO nazvaná Nette\Database\Connection:

use Nette\Database\Connection;

$database = new Connection($dsn, $user, $password);

Po připojení se automaticky zobrazí panel na Debugger baru. Ten nás informuje o všech vykonaných SQL dotazech, době jejich vyřízení, počtu vrácených řádků, dokonce uvádí i jejich EXPLAIN podobu a místo, v kódu, kde byl dotaz volán.

Oproti PDO dovoluje Connection uvádět v příkazech exec a query výčet parametrů:

$database->exec('INSERT INTO users', array( // parametrem může být pole
    'name' => 'Jim',
    'created' => new DateTime, // nebo objekt DateTime
    'avatar' => fopen('image.gif', 'r'), // nebo soubor
), ...); // lze použít i vícenásobný insert

$database->exec('UPDATE users SET ? WHERE id=?', $data, $id);

$database->query('SELECT * FROM categories WHERE id=?', 123)->dump();

Práce s tabulkami

Nette\Database používá pro svoji práci cizí klíče a ty bohužel typ tabulky MyISAM nepodporuje, pro správnou funkčnost vytvořte následující tabulky jako InnoDB

Pro složitější výběry lze použít nástroj, který vychází z výborné knihovny NotORM a nabízí čitelnější API. Databázi na obrázku lze procházet takto:

Příklad SQL databáze

foreach ($database->table('book')->order('title')->limit(5) as $book)
{
    echo $book->title, ' (', $book->author->name, ')';
    // ekvivalentní s $book['title'], ' (', $book['author']['name'], ')';

    foreach ($book->related('book_tag') as $book_tag) {
        echo $book_tag->tag->name . ', ';
    }
}

V šabloně by se použil pochopitelně Latte-zápis:

{foreach $database->table('book')->order('title')->limit(5) as $book}
    <h2>{$book->title} ({$book->author->name})</h2>

    {foreach $book->related('book_tag') as $book_tag}
        {$book_tag->tag->name}{sep}, {/sep}
    {/foreach}
{/foreach}

Efektivita

Budete nadšeni, jak efektivně databázová vrstva pracuje. Žádné sloupce se zbytečně nepřenášejí vícekrát. Uvedený příklad pokládá tyto dotazy:

SELECT * FROM `book` ORDER BY title LIMIT 5

SELECT * FROM `author` WHERE (`author`.`id` IN (11, 12))

SELECT * FROM `book_tag` WHERE (`book_tag`.`book_id` IN (1, 4, 2, 3))

SELECT * FROM `tag` WHERE (`tag`.`id` IN (21, 22, 23))

Při použití cache (zatím neimplementováno) se umí dotazovat jen na sloupce, které se skutečně použijí:

SELECT `id`, `title`, `author_id` FROM `book` ORDER BY title LIMIT 5

SELECT `id`, `name` FROM `author` WHERE (`author`.`id` IN (11, 12))

SELECT `book_id`, `tag_id` FROM `book_tag` WHERE (`book_tag`.`book_id` IN (1, 4, 2, 3))

SELECT `id`, `name` FROM `tag` WHERE (`tag`.`id` IN (21, 22, 23))

Table Selection API

(převzato z NotORM API)

$table = $conn->table($tableName) Get representation of table $tableName
$table->find($value) Search by primary key
$table->where($where[, $parameters[, ...]]) Set WHERE (explained later)
$table->order($columns) Set ORDER BY, can be expression ('column DESC, id DESC')
$table->select($columns) Set retrieved columns, can be expression ('col, MD5(col) AS hash')
$table->limit($limit[, $offset]) Set LIMIT and OFFSET
$table->group($columns[, $having]) Set GROUP BY and HAVING

Výrazy lze zřetězit, např. $table->where(...)->order(...)->limit(...). Více podmínek where se spojuje operátorem AND.

$table->where("field", $value) Means field = $value
$table->where("field", NULL) Means field IS NULL
$table->where("field > ?", $val) Means field > $val
$table->where("field", array(1, 2)) Means field IN (1, 2)
$table->where("field", $conn->table($tableName)) Means field IN (SELECT $primary FROM $tableName)
$table->where("field", $conn->table($tableName)->select('col')) Means field IN (SELECT col FROM $tableName)
$table->where(array("field" => "x", "field2" => "y")) Same as $table->where("field", "x")->where("field2", "y")

Pokud použijeme tečkovou notaci ("$table.$column"), automaticky se vytvoří spojení s odkazovanou tabulkou.

Lze také vytvářet agregační dotazy:

$table->count("*") Get number of rows
$table->count("DISTINCT $column") Get number of distinct values
$table->min($column) Get minimum value
$table->max($column) Get maximum value
$table->aggregation("GROUP_CONCAT($column)") Run any aggregation function

Získávání dat:

foreach ($table as $id => $row) Iterate all rows in result
$row = $table->get($id) Get single row with ID $id from table
$row = $table[$id] Get row with ID $id from the result
$row = $table->fetch() Get next row from the result
$array = $table->fetchPairs($key, $value) Fetch all values to associative array
$array = $table->fetchPairs($key) Fetch all rows to associative array
count($table) Get number of rows in result set

Práce s jedním řádkem:

$data = $row[$column] nebo $row->$column Vrátí hodnotu atributu $column nebo jednu řádku z tabulky rodiče. Např. $book['title'] == $book->title nebo $book['author'] == $book->author == $book->ref('author')
$rodic = $dite->ref($tableName) Vrátí jednu řádku z cizí tabulky (rodič). Např. $book->ref('author')->name
$tabulkaDeti = $rodic->related($tableName) Vrátí tabulku dětí již odfiltrovanou hodnotou primárního klíče rodiče. Použije se atribut tabulky dětí odvozený od názvu tabulky rodiče. Např. $author->related('book')->count()
$tabulkaDeti = $rodic->related($tableName, $column) Použije konkrétní atribut tabulky dětí pro filtrování. Např. $author->related('book', 'maintainer_id')->count()
(string) $row Vrátí hodnotu primárního klíče