Edit
Lang

Databáze

Nette Framework ná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

Třída Nette\Database\Connection tvoří obálku nad PDO a reprezentuje připojení k databázi. Tato třída také poskyuje základní funkcionalitu pokládání dotazů. Vstupní bránou do vrstvy Nette\Database\Table, která poskytuje pokročilou pro práci s tabulkami, je pak třída Nette\Database\Context. .

Vytvoření připojení

Pro vytvoření nového připojení k databázi stačí vytvořit novou instanci třídy Nette\Database\Connection. To provedeme buď pomocí aplikační konfigurace nebo v případě, kdy používáme Nette\Database samostatně, následovně:

use Nette\Database\Connection;
$connection = new Connection($dsn, $user, $password);

Více informací v odstavci pokročilé nastavení spojení

Vytvoření pomocí aplikační konfigurace

Nejjednodušším způsobem, jak nastavit připojení k databázi, je v aplikační konfiguraci, která umožňuje vytvoření více připojení a také usnadňuje přidání panelu databáze do Tracy debugger baru. Tento zápis vytvoří krom Nette\Database\Connection také službu Nette\Database\Context, která je nutná pro práci s vrstvou Database\Table.

database:
    default:
        dsn: "mysql:host=127.0.0.1;dbname=test"
        user: "root"
        password: "password"
        options:
            lazy: true

Více informací v odstavci pokročilé nastavení spojení

Dotazy

Database\Connection umožňuje jednoduše pokládat databázové dotazy voláním metody query, která nám vrací ResultSet.

$connection->query('INSERT INTO users', array( // parametr může být pole
    'name' => 'Jim',
    'created' => new DateTime, // nebo objekt DateTime
    'avatar' => fopen('image.gif', 'r'), // nebo soubor
), ...); // je možné také provést více vložení najednou

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

$result = $connection>query('SELECT * FROM users WHERE id=?', 123);

//ResultSet implemetuje iterator
foreach ($result as $row) {
    echo $row['name'];
}

$rows = $result->fetch(); //vrátí následující řádek nebo FALSE
$rows = $result->fetchAll(); //vrátí všechny řádky jako pole

Nad třídou ResultSet je možné iterovat pouze jednou, pokud potřebujeme iterovat vícekrát, je nutno tento objekt převést na pole metodou fetchAll()

Podporované databáze

Nette\Database si vytvoří vlastní vnitřní ovladač a nastaví své chování podle toho, jaký používáte databázový server. Nette podporuje následující databáze:

Databázový server DSN jméno Podpora v Database Podpora v Database\Table
MySQL mysql ANO ANO
PostgreSQL pgsql ANO ANO
Sqlite 3 sqlite ANO ANO
Sqlite 2 sqlite2 ANO
Oracle oci ANO
MS SQL (PDO_SQLSRV) sqlsrv ANO ANO
MS SQL (PDO_DBLIB) mssql ANO
ODBC odbc ANO

Pokročilé nastavení spojení

Volitelný čtvrtý parametr konstruktoru Connection umožňuje přidat dodatečné parametry. Tyto volby jsou předány jak konstruktoru PDO, tak vnitřnímu ovladači, mohou tedy obsahovat konfiguraci pro instanci PDO i pro instanci ovladače.

Připojení může být vytvořeno „líně“. To znamená, že připojení k databázi je navázáno až ve chvíli, kdy je poprvé potřeba, ne když je vytvořena instance Connection. Toto chování můžeme zapnout přidáním konfigurace 'lazy' => TRUE.

Ovladač databáze je zvolen podle použitého DSN jména. Můžeme ale poskytnout vlastní implementaci ovladače. To uděláme předáním jména ovladače jako hodnoty parametru driverClass.

$connection = new Connection($dsn, $user, $password, [
    'lazy' => FALSE,
    'driverClass' => 'App\JmenoVasiVlastniImplementaceOvladace'
]);

V běžné Nette aplikaci, kde používáme celé Nette a nikoliv jen samostatnou databázovou vrstvu, vytváříme vždy spojení pomocí aplikační konfigurace. Ta je velmi intuitivní a umožní nám také snadno používat vrstvu Database\Table:

database:
    default:
        dsn:          "mysql:host=127.0.0.1;dbname=test"
        user:         "root"
        password:     "password"
        options:
            PDO::MYSQL_ATTR_COMPRESS: true
            lazy: true
        debugger:     true        # panel v debugger baru
        explain:      true        # explain dotazů v debugger bar
        conventions:  discovered  # nebo static nebo vaší jméno třídy, výchozí je discovered
        autowired: true # defaultní u prvního spojení
    anotherConnection:
        dsn: ...
        autowired: false #defaultní u druhého a dalšího spojení

Práce se databázovými službami

Každé takto definované spojení vytvoří dvě služby – Nette\Database\Connection pod názvem database.[NAME].connection (tedy např. database.default.connection) a Nette\Database\Context pod názvem database.[NAME].context (např. database.default.context).

Pokud si při práci s databází vystačíme s psaním SQL dotazů, jako jsme viděli v této kapitole, bude nám stačit první jmenovaná služba. Pokud však chceme využívat všechny možnosti vrstvy Database\Table, musíme pracovat se službou Context.

V případě, že používáme pouze jedno databázové spojení, nemusíme se o nic starat a vyžádáme si jej pomocí DI.

class UserManager
{

    private $connection;

    public function __construct(Nette\Database\Connection $connection)
    {
        $this->connection = $connection;
        //nebo  si vyzadame Nette\Database\Context, pokud chceme pracovat s Database\Table
    }
}

Jestliže však máme definováno více spojení, je nutné ta spojení, která nejsou autowirovaná (obvykle druhé a následující) předat ručně v konfiguraci:

services:
    - UserManager(@database.anotherConnection.connection) #nebo @database.anotherConnection.context