Nette Database
Nette Database – мощный и изящный слой работы с базой данных для PHP, нацеленный на простоту и продуманные возможности. Он предлагает два способа работы с базой: Explorer для быстрой разработки приложений или SQL-подход для прямой работы с запросами.
SQL-подход
- Безопасные параметризованные запросы
- Точный контроль над структурой SQL-запроса
- Когда нужно писать сложные запросы с продвинутыми функциями
- Оптимизация производительности через конкретные функции SQL
Explorer
- Быстрая разработка без написания SQL
- Интуитивная работа со связями между таблицами
- Выигрыш от автоматической оптимизации запросов
- Подходит для быстрой и удобной работы с базой данных
Установка
Скачайте и установите библиотеку с помощью Composer:
composer require nette/database
Поддерживаемые базы данных
Nette Database поддерживает следующие базы данных:
| Сервер базы данных | Имя DSN | Поддержка Explorer |
|---|---|---|
| MySQL (>= 5.1) | mysql | ДА |
| PostgreSQL (>= 9.0) | pgsql | ДА |
| SQLite 3 (>= 3.8) | sqlite | ДА |
| Oracle | oci | НЕТ |
| MS SQL (PDO_SQLSRV) | sqlsrv | ДА |
| MS SQL (PDO_DBLIB) | mssql | НЕТ |
| ODBC | odbc | НЕТ |
Два подхода к работе с базой данных
Nette Database даёт вам выбор: вы можете либо писать SQL-запросы напрямую (SQL-подход), либо позволить порождать их автоматически (Explorer). Посмотрим, как оба подхода справляются с одними и теми же задачами:
SQL-подход – SQL-запросы
// Вставка записи
$database->query('INSERT INTO books', [
'author_id' => $authorId,
'title' => $bookData->title,
'published_at' => new DateTime,
]);
// Получение записей: авторы книг
$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
');
// Вывод (не оптимально, порождает N дополнительных запросов)
foreach ($result as $author) {
$books = $database->query('
SELECT * FROM books
WHERE author_id = ?
ORDER BY published_at DESC
', $author->id);
echo "Author $author->name has written $author->books_count books:\n";
foreach ($books as $book) {
echo "- $book->title\n";
}
}
Подход Explorer – автоматическое порождение SQL
// Вставка записи
$database->table('books')->insert([
'author_id' => $authorId,
'title' => $bookData->title,
'published_at' => new DateTime,
]);
// Получение записей: авторы книг
$authors = $database->table('authors')
->where('active', 1);
// Вывод (автоматически порождает всего 2 оптимизированных запроса)
foreach ($authors as $author) {
$books = $author->related('books')
->order('published_at DESC');
echo "Author $author->name has written {$books->count()} books:\n";
foreach ($books as $book) {
echo "- $book->title\n";
}
}
Подход Explorer порождает и оптимизирует SQL-запросы автоматически. В примере выше SQL-подход порождает N+1 запросов (один для авторов и затем по одному для книг каждого автора), тогда как Explorer автоматически оптимизирует запросы и выполняет только два: один для авторов и один для всех их книг.
Оба подхода можно свободно сочетать в приложении по мере надобности.
Соединение и настройка
Чтобы подключиться к базе данных, достаточно создать экземпляр класса Nette\Database\Connection:
$database = new Nette\Database\Connection($dsn, $user, $password);
Параметр $dsn (Data Source Name) такой же, какой использует PDO,
например host=127.0.0.1;dbname=test. В случае неудачи он выбрасывает
Nette\Database\ConnectionException.
Однако более удобный способ предлагает конфигурация
приложения, где достаточно добавить секцию database. Так
создаются нужные объекты, а также панель базы данных в панели Tracy.
database:
dsn: 'mysql:host=127.0.0.1;dbname=test'
user: root
password: password
Затем объект соединения можно получить как сервис из DI-контейнера, например:
class Model
{
public function __construct(
// или Nette\Database\Explorer
private Nette\Database\Connection $database,
) {
}
}
Подробнее о конфигурации базы данных.
Создание Explorer вручную
Если вы не используете DI-контейнер Nette, вы можете создать экземпляр
Nette\Database\Explorer вручную:
// соединение с базой данных
$connection = new Nette\Database\Connection('mysql:host=127.0.0.1;dbname=mydatabase', 'user', 'password');
// хранилище кеша, реализующее Nette\Caching\Storage, например:
$storage = new Nette\Caching\Storages\FileStorage('/path/to/temp/dir');
// занимается рефлексией структуры базы данных
$structure = new Nette\Database\Structure($connection, $storage);
// задаёт правила отображения имён таблиц, столбцов и внешних ключей
$conventions = new Nette\Database\Conventions\DiscoveredConventions($structure);
$explorer = new Nette\Database\Explorer($connection, $structure, $conventions, $storage);
Управление соединением
При создании объекта Connection соединение устанавливается
автоматически. Если вы хотите отложить соединение, используйте
ленивый режим: включите его в конфигурации
параметром lazy или так:
$database = new Nette\Database\Connection($dsn, $user, $password, ['lazy' => true]);
Для управления соединением служат методы connect(), disconnect()
и reconnect().
connect()создаёт соединение, если его ещё нет, и может выброситьNette\Database\ConnectionException.disconnect()разрывает текущее соединение с базой данных.reconnect()выполняет разрыв и последующее повторное подключение к базе данных. Этот метод тоже может выброситьNette\Database\ConnectionException.
Кроме того, вы можете следить за событиями, связанными с соединением,
через событие onConnect, которое представляет собой массив
callback-функций, вызываемых после установки соединения с базой данных.
// выполняется после подключения к базе данных
$database->onConnect[] = function($database) {
echo "Connected to the database";
};
Похожим образом работает событие onQuery: это массив
callback-функций, вызываемых после каждого выполненного запроса (и когда
запрос завершается ошибкой), что удобно для логирования или
профилирования.
Панель отладки Tracy
Если вы используете Tracy, панель Database в Debug Bar включается автоматически. Она показывает все выполненные запросы, их параметры, время выполнения и место в коде, откуда они были вызваны.
