Nette Database
**************
.[perex]
Nette Database je výkonná a elegantní databázová vrstva pro PHP s důrazem na jednoduchost a chytré funkce. Nabízí dva způsoby práce s databází - [Explorer] pro rychlý vývoj aplikací, nebo [SQL přístup |SQL way] pro přímou práci s dotazy.
<div class="grid gap-3">
<div>
[SQL přístup |SQL way]
======================
- Bezpečné parametrizované dotazy
- Přesná kontrola nad podobou SQL dotazů
- Když píšete komplexní dotazy s pokročilými funkcemi
- Optimalizujete výkon pomocí specifických SQL funkcí
</div>
<div>
[Explorer]
==========
- Vyvíjíte rychle bez psaní SQL
- Intuitivní práce s relacemi mezi tabulkami
- Oceníte automatickou optimalizaci dotazů
- Vhodné pro rychlou a pohodlnou práci s databází
</div>
</div>
Instalace
=========
Knihovnu stáhnete a nainstalujete pomocí nástroje [Composer|best-practices:composer]:
```shell
composer require nette/database
```
Podporované databáze
====================
Nette Database podporuje následující databáze:
|* Databázový server |* DSN jméno |* Podpora v Explorer
|---------------------|-------------|-----------------------
| MySQL (>= 5.1) | mysql | ANO
| PostgreSQL (>= 9.0) | pgsql | ANO
| Sqlite 3 (>= 3.8) | sqlite | ANO
| Oracle | oci | -
| MS SQL (PDO_SQLSRV) | sqlsrv | ANO
| MS SQL (PDO_DBLIB) | mssql | -
| ODBC | odbc | -
Dva přístupy k databázi
=======================
Nette Database vám dává na výběr: můžete buď psát SQL dotazy přímo (SQL přístup), nebo je nechat generovat automaticky (Explorer). Podívejme se, jak oba přístupy řeší stejné úkoly:
[SQL přístup|sql way] - SQL dotazy
```php
// vložení záznamu
$database->query('INSERT INTO books', [
'author_id' => $authorId,
'title' => $bookData->title,
'published_at' => new DateTime,
]);
// získání záznamů: autoři knih
$result = $database->query('
SELECT authors.*, COUNT(books.id) AS books_count
FROM authors
LEFT JOIN books ON authors.id = books.author_id
WHERE authors.active = 1
GROUP BY authors.id
');
// výpis (není optimální, generuje N dalších dotazů)
foreach ($result as $author) {
$books = $database->query('
SELECT * FROM books
WHERE author_id = ?
ORDER BY published_at DESC
', $author->id);
echo "Autor $author->name napsal $author->books_count knih:\n";
foreach ($books as $book) {
echo "- $book->title\n";
}
}
```
[Explorer přístup|explorer] - automatické generování SQL
```php
// vložení záznamu
$database->table('books')->insert([
'author_id' => $authorId,
'title' => $bookData->title,
'published_at' => new DateTime,
]);
// získání záznamů: autoři knih
$authors = $database->table('authors')
->where('active', 1);
// výpis (automaticky generuje jen 2 optimalizované dotazy)
foreach ($authors as $author) {
$books = $author->related('books')
->order('published_at DESC');
echo "Autor $author->name napsal {$books->count()} knih:\n";
foreach ($books as $book) {
echo "- $book->title\n";
}
}
```
Explorer přístup generuje a optimalizuje SQL dotazy automaticky. V uvedeném příkladu SQL přístup vygeneruje N+1 dotazů (jeden pro autory a pak jeden pro knihy každého autora), zatímco Explorer automaticky optimalizuje dotazy a provede pouze dva - jeden pro autory a jeden pro všechny jejich knihy.
Oba přístupy lze v aplikaci libovolně kombinovat podle potřeby.
Připojení a konfigurace
=======================
Pro připojení k databázi stačí vytvořit instanci třídy [api:Nette\Database\Connection]:
```php
$database = new Nette\Database\Connection($dsn, $user, $password);
```
Parametr `$dsn` (data source name) je stejný, [jaký používá PDO |https://www.php.net/manual/en/pdo.construct.php#refsect1-pdo.construct-parameters], např. `host=127.0.0.1;dbname=test`. V případě selhání vyhodí výjimku `Nette\Database\ConnectionException`.
Nicméně šikovnější způsob nabízí [aplikační konfigurace |configuration], kam stačí přidat sekci `database` a vytvoří se potřebné objekty a také databázový panel v [Tracy |tracy:] baru.
```neon
database:
dsn: 'mysql:host=127.0.0.1;dbname=test'
user: root
password: password
```
Poté objekt spojení [získáme jako službu z DI kontejneru |dependency-injection:passing-dependencies], např.:
```php
class Model
{
public function __construct(
// nebo Nette\Database\Explorer
private Nette\Database\Connection $database,
) {
}
}
```
Více informací o [konfiguraci databáze|configuration].
Ruční vytvoření Explorer
------------------------
Pokud nepoužíváte Nette DI kontejner, můžete instanci `Nette\Database\Explorer` vytvořit ručně:
```php
// připojení k databázi
$connection = new Nette\Database\Connection('mysql:host=127.0.0.1;dbname=mydatabase', 'user', 'password');
// úložiště pro cache, implementuje Nette\Caching\Storage, např.:
$storage = new Nette\Caching\Storages\FileStorage('/path/to/temp/dir');
// stará se o reflexi databázové struktury
$structure = new Nette\Database\Structure($connection, $storage);
// definuje pravidla pro mapování názvů tabulek, sloupců a cizích klíčů
$conventions = new Nette\Database\Conventions\DiscoveredConventions($structure);
$explorer = new Nette\Database\Explorer($connection, $structure, $conventions, $storage);
```
Správa připojení
================
Při vytvoření objektu `Connection` dojde automaticky k připojení. Pokud chcete připojení odložit, použijte lazy režim - ten zapnete v [konfiguraci|configuration] nastavením `lazy`, nebo takto:
```php
$database = new Nette\Database\Connection($dsn, $user, $password, ['lazy' => true]);
```
Pro správu připojení využijte metody `connect()`, `disconnect()` a `reconnect()`.
- `connect()` vytvoří připojení, pokud ještě neexistuje, přičemž může vyvolat výjimku `Nette\Database\ConnectionException`.
- `disconnect()` odpojí aktuální připojení k databázi.
- `reconnect()` provede odpojení a následné opětovné připojení k databázi. Tato metoda může rovněž vyvolat výjimku `Nette\Database\ConnectionException`.
Kromě toho můžete sledovat události spojené s připojením pomocí události `onConnect`, což je pole callbacků, které se zavolají po navázání spojení s databází.
```php
// proběhne po připojení k databázi
$database->onConnect[] = function($database) {
echo "Připojeno k databázi";
};
```
Událost `onQuery` funguje podobně - je to pole callbacků, které se zavolají po každém provedeném dotazu (i při jeho selhání), což se hodí pro logování nebo profilování.
Tracy Debug Bar
===============
Pokud používáte [Tracy |tracy:], aktivuje se automaticky panel Database v Debug baru, který zobrazuje všechny provedené dotazy, jejich parametry, dobu vykonání a místo v kódu, kde byly zavolány.
[* db-panel.webp *]
{{maintitle: Začínáme s Nette Database: Explorer, nebo SQL}}
{{description: Nainstalujte Nette Database, připojte se k MySQL, PostgreSQL, SQLite nebo MS SQL a vyberte si přístup: Explorer pro rychlý vývoj, nebo SQL pro plnou kontrolu.}}
Nette Database
Nette Database je výkonná a elegantní databázová vrstva pro PHP s důrazem na jednoduchost a chytré
funkce. Nabízí dva způsoby práce s databází – Explorer pro
rychlý vývoj aplikací, nebo SQL přístup pro přímou práci
s dotazy.
Knihovnu stáhnete a nainstalujete pomocí nástroje Composer:
composer require nette/database
Podporované databáze
Nette Database podporuje následující databáze:
Databázový server
DSN jméno
Podpora v Explorer
MySQL (>= 5.1)
mysql
ANO
PostgreSQL (>= 9.0)
pgsql
ANO
Sqlite 3 (>= 3.8)
sqlite
ANO
Oracle
oci
–
MS SQL (PDO_SQLSRV)
sqlsrv
ANO
MS SQL (PDO_DBLIB)
mssql
–
ODBC
odbc
–
Dva přístupy k databázi
Nette Database vám dává na výběr: můžete buď psát SQL dotazy přímo (SQL přístup), nebo je nechat generovat
automaticky (Explorer). Podívejme se, jak oba přístupy řeší stejné úkoly:
// vložení záznamu
$database->query('INSERT INTO books', [
'author_id' => $authorId,
'title' => $bookData->title,
'published_at' => new DateTime,
]);
// získání záznamů: autoři knih
$result = $database->query('
SELECT authors.*, COUNT(books.id) AS books_count
FROM authors
LEFT JOIN books ON authors.id = books.author_id
WHERE authors.active = 1
GROUP BY authors.id
');
// výpis (není optimální, generuje N dalších dotazů)
foreach ($result as $author) {
$books = $database->query('
SELECT * FROM books
WHERE author_id = ?
ORDER BY published_at DESC
', $author->id);
echo "Autor $author->name napsal $author->books_count knih:\n";
foreach ($books as $book) {
echo "- $book->title\n";
}
}
// vložení záznamu
$database->table('books')->insert([
'author_id' => $authorId,
'title' => $bookData->title,
'published_at' => new DateTime,
]);
// získání záznamů: autoři knih
$authors = $database->table('authors')
->where('active', 1);
// výpis (automaticky generuje jen 2 optimalizované dotazy)
foreach ($authors as $author) {
$books = $author->related('books')
->order('published_at DESC');
echo "Autor $author->name napsal {$books->count()} knih:\n";
foreach ($books as $book) {
echo "- $book->title\n";
}
}
Explorer přístup generuje a optimalizuje SQL dotazy automaticky. V uvedeném příkladu SQL přístup vygeneruje
N+1 dotazů (jeden pro autory a pak jeden pro knihy každého autora), zatímco Explorer automaticky optimalizuje dotazy a
provede pouze dva – jeden pro autory a jeden pro všechny jejich knihy.
Oba přístupy lze v aplikaci libovolně kombinovat podle potřeby.
$database = new Nette\Database\Connection($dsn, $user, $password);
Parametr $dsn (data source name) je stejný, jaký používá PDO, např.
host=127.0.0.1;dbname=test. V případě selhání vyhodí výjimku
Nette\Database\ConnectionException.
Nicméně šikovnější způsob nabízí aplikační
konfigurace, kam stačí přidat sekci database a vytvoří se potřebné objekty a také databázový panel
v Tracy baru.
Pokud nepoužíváte Nette DI kontejner, můžete instanci Nette\Database\Explorer vytvořit ručně:
// připojení k databázi
$connection = new Nette\Database\Connection('mysql:host=127.0.0.1;dbname=mydatabase', 'user', 'password');
// úložiště pro cache, implementuje Nette\Caching\Storage, např.:
$storage = new Nette\Caching\Storages\FileStorage('/path/to/temp/dir');
// stará se o reflexi databázové struktury
$structure = new Nette\Database\Structure($connection, $storage);
// definuje pravidla pro mapování názvů tabulek, sloupců a cizích klíčů
$conventions = new Nette\Database\Conventions\DiscoveredConventions($structure);
$explorer = new Nette\Database\Explorer($connection, $structure, $conventions, $storage);
Správa připojení
Při vytvoření objektu Connection dojde automaticky k připojení. Pokud chcete připojení odložit, použijte
lazy režim – ten zapnete v konfiguraci nastavením
lazy, nebo takto:
$database = new Nette\Database\Connection($dsn, $user, $password, ['lazy' => true]);
Pro správu připojení využijte metody connect(), disconnect() a reconnect().
connect() vytvoří připojení, pokud ještě neexistuje, přičemž může vyvolat výjimku
Nette\Database\ConnectionException.
disconnect() odpojí aktuální připojení k databázi.
reconnect() provede odpojení a následné opětovné připojení k databázi. Tato metoda může rovněž
vyvolat výjimku Nette\Database\ConnectionException.
Kromě toho můžete sledovat události spojené s připojením pomocí události onConnect, což je pole
callbacků, které se zavolají po navázání spojení s databází.
// proběhne po připojení k databázi
$database->onConnect[] = function($database) {
echo "Připojeno k databázi";
};
Událost onQuery funguje podobně – je to pole callbacků, které se zavolají po každém provedeném dotazu
(i při jeho selhání), což se hodí pro logování nebo profilování.
Tracy Debug Bar
Pokud používáte Tracy, aktivuje se automaticky panel Database v Debug baru,
který zobrazuje všechny provedené dotazy, jejich parametry, dobu vykonání a místo v kódu, kde byly zavolány.