Nette Database
Nette Database to wydajna i elegancka warstwa bazodanowa dla PHP z naciskiem na prostotę i inteligentne funkcje. Oferuje dwa sposoby pracy z bazą danych – Explorer dla szybkiego rozwoju aplikacji, lub Dostęp SQL dla bezpośredniej pracy z zapytaniami.
Dostęp SQL
- Bezpieczne sparametryzowane zapytania
- Dokładna kontrola nad formą zapytań SQL
- Gdy piszesz złożone zapytania z zaawansowanymi funkcjami
- Optymalizujesz wydajność za pomocą specyficznych funkcji SQL
Explorer
- Rozwijasz szybko bez pisania SQL
- Intuicyjna praca z relacjami między tabelami
- Docenisz automatyczną optymalizację zapytań
- Odpowiednie do szybkiej i wygodnej pracy z bazą danych
Instalacja
Bibliotekę można pobrać i zainstalować za pomocą narzędzia Composer:
composer require nette/database
Obsługiwane bazy danych
Nette Database obsługuje następujące bazy danych:
Serwer bazy danych | Nazwa DSN | Wsparcie w Explorer |
---|---|---|
MySQL (>= 5.1) | mysql | TAK |
PostgreSQL (>= 9.0) | pgsql | TAK |
Sqlite 3 (>= 3.8) | sqlite | TAK |
Oracle | oci | – |
MS SQL (PDO_SQLSRV) | sqlsrv | TAK |
MS SQL (PDO_DBLIB) | mssql | – |
ODBC | odbc | – |
Dwa podejścia do bazy danych
Nette Database daje Ci wybór: możesz pisać zapytania SQL bezpośrednio (dostęp SQL) lub pozwolić na ich automatyczne generowanie (Explorer). Zobaczmy, jak oba podejścia rozwiązują te same zadania:
Dostęp SQL – Zapytania SQL
// wstawienie rekordu
$database->query('INSERT INTO books', [
'author_id' => $authorId,
'title' => $bookData->title,
'published_at' => new DateTime,
]);
// pobranie rekordów: autorzy książek
$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
');
// wypisanie (nie jest optymalne, generuje N dodatkowych zapytań)
foreach ($result as $author) {
$books = $database->query('
SELECT * FROM books
WHERE author_id = ?
ORDER BY published_at DESC
', $author->id);
echo "Autor $author->name napisał $author->books_count książek:\n";
foreach ($books as $book) {
echo "- $book->title\n";
}
}
Podejście Explorer – automatyczne generowanie SQL
// wstawienie rekordu
$database->table('books')->insert([
'author_id' => $authorId,
'title' => $bookData->title,
'published_at' => new DateTime,
]);
// pobranie rekordów: autorzy książek
$authors = $database->table('authors')
->where('active', 1);
// wypisanie (automatycznie generuje tylko 2 zoptymalizowane zapytania)
foreach ($authors as $author) {
$books = $author->related('books')
->order('published_at DESC');
echo "Autor $author->name napisał {$books->count()} książek:\n";
foreach ($books as $book) {
echo "- $book->title\n";
}
}
Podejście Explorer generuje i optymalizuje zapytania SQL automatycznie. W podanym przykładzie podejście SQL wygeneruje N+1 zapytań (jedno dla autorów, a następnie jedno dla książek każdego autora), podczas gdy Explorer automatycznie optymalizuje zapytania i wykonuje tylko dwa – jedno dla autorów i jedno dla wszystkich ich książek.
Oba podejścia można dowolnie łączyć w aplikacji w zależności od potrzeb.
Połączenie i konfiguracja
Aby połączyć się z bazą danych, wystarczy utworzyć instancję klasy Nette\Database\Connection:
$database = new Nette\Database\Connection($dsn, $user, $password);
Parametr $dsn
(data source name) jest taki sam, jakiego używa PDO, np.
host=127.0.0.1;dbname=test
. W przypadku niepowodzenia rzuca wyjątek
Nette\Database\ConnectionException
.
Jednak wygodniejszy sposób oferuje konfiguracja aplikacji, gdzie
wystarczy dodać sekcję database
, a zostaną utworzone potrzebne obiekty oraz panel bazy danych w pasku Tracy.
database:
dsn: 'mysql:host=127.0.0.1;dbname=test'
user: root
password: password
Następnie obiekt połączenia uzyskujemy jako usługę z kontenera DI, np.:
class Model
{
public function __construct(
// lub Nette\Database\Explorer
private Nette\Database\Connection $database,
) {
}
}
Więcej informacji o konfiguracji bazy danych.
Ręczne tworzenie Explorera
Jeśli nie używasz kontenera Nette DI, możesz utworzyć instancję Nette\Database\Explorer
ręcznie:
// połączenie z bazą danych
$connection = new Nette\Database\Connection('mysql:host=127.0.0.1;dbname=mydatabase', 'user', 'password');
// magazyn dla cache, implementuje Nette\Caching\Storage, np.:
$storage = new Nette\Caching\Storages\FileStorage('/path/to/temp/dir');
// zajmuje się refleksją struktury bazy danych
$structure = new Nette\Database\Structure($connection, $storage);
// definiuje reguły mapowania nazw tabel, kolumn i kluczy obcych
$conventions = new Nette\Database\Conventions\DiscoveredConventions($structure);
$explorer = new Nette\Database\Explorer($connection, $structure, $conventions, $storage);
Zarządzanie połączeniem
Podczas tworzenia obiektu Connection
połączenie jest nawiązywane automatycznie. Jeśli chcesz odłożyć
połączenie, użyj trybu lazy – włączysz go w konfiguracji
ustawiając lazy
, lub w ten sposób:
$database = new Nette\Database\Connection($dsn, $user, $password, ['lazy' => true]);
Do zarządzania połączeniem użyj metod connect()
, disconnect()
i reconnect()
.
connect()
tworzy połączenie, jeśli jeszcze nie istnieje, przy czym może rzucić wyjątekNette\Database\ConnectionException
.disconnect()
rozłącza bieżące połączenie z bazą danych.reconnect()
wykonuje rozłączenie i ponowne połączenie z bazą danych. Ta metoda również może rzucić wyjątekNette\Database\ConnectionException
.
Ponadto możesz śledzić zdarzenia związane z połączeniem za pomocą zdarzenia onConnect
, które jest
tablicą callbacków wywoływanych po nawiązaniu połączenia z bazą danych.
// wykonuje się po połączeniu z bazą danych
$database->onConnect[] = function($database) {
echo "Połączono z bazą danych";
};
Pasek Debugowania Tracy
Jeśli używasz Tracy, panel Database w pasku Debugowania aktywuje się automatycznie, wyświetlając wszystkie wykonane zapytania, ich parametry, czas wykonania oraz miejsce w kodzie, gdzie zostały wywołane.
