SQLite встроен в PHP по умолчанию — никаких серверов, никакой установки. Файл базы данных лежит рядом с проектом, и этого достаточно для большинства задач: лендинги, парсеры, кеш, небольшие API. В этой статье — всё что нужно для работы с SQLite в PHP: два способа подключения, основные запросы, ORM, оптимизация производительности и удалённый доступ.
- PDO vs SQLite3: какой интерфейс выбрать
- Подключение к SQLite через PDO
- Подключение через класс SQLite3
- SELECT: выборка данных
- Через PDO
- Через SQLite3
- INSERT, UPDATE, DELETE
- INSERT через PDO
- UPDATE и DELETE через PDO
- INSERT через SQLite3
- Создание таблиц из PHP
- Транзакции: массовая вставка данных
- PHP SQLite ORM: ORM::for_table и альтернативы
- Установка Idiorm через Composer
- Подключение к SQLite
- ORM::for_table() — основные операции
- ORM::close() — закрытие соединения
- Альтернативы Idiorm для SQLite
- Оптимизация производительности PHP + SQLite
- 1. WAL-режим — ускорить параллельное чтение
- 2. Кеш в памяти — ускорить чтение
- 3. Индексы — ускорить SELECT
- 4. Synchronous OFF — для некритичных данных
- 5. Итоговый набор PRAGMA для PHP-проекта
- Удалённый доступ к SQLite через PHP
- Вариант 1 — простой REST API на чистом PHP
- Вариант 2 — PHPLiteAdmin (веб-интерфейс)
- Практический пример: сохранение заявок с лендинга
- Когда SQLite не подходит для PHP-проекта
- Изучите SQLite подробнее
PDO vs SQLite3: какой интерфейс выбрать
В PHP есть два способа работать с SQLite: через универсальный PDO и через специализированный класс SQLite3. Оба входят в стандартную поставку PHP.
| Критерий | PDO | SQLite3 |
|---|---|---|
| Переносимость | ✅ Работает с MySQL, PostgreSQL, SQLite — один интерфейс | ❌ Только SQLite |
| Производительность | Чуть медленнее из-за абстракции | ✅ Быстрее на прямых запросах |
| Prepare/execute | ✅ Полноценно | ✅ Полноценно |
| Транзакции | ✅ | ✅ |
| Подходит для | Проект может переехать на MySQL; командная разработка | Только SQLite, максимальная скорость |
Рекомендация: используйте PDO если есть шанс переехать на другую СУБД. Используйте SQLite3 если нужна максимальная скорость в SQLite-only проекте.
Подключение к SQLite через PDO
Убедитесь что расширение включено в php.ini:
extension=pdo_sqlite
Подключение к файлу базы данных:
<?php
$pdo = new PDO('sqlite:' . __DIR__ . '/database.db');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
Для базы только в памяти (например в тестах):
$pdo = new PDO('sqlite::memory:');
Важно: путь к файлу должен быть абсолютным. Используйте __DIR__ чтобы путь не зависел от рабочей директории скрипта.
Подключение через класс SQLite3
Расширение в php.ini:
extension=sqlite3
<?php
$db = new SQLite3(__DIR__ . '/database.db');
// Включить исключения вместо предупреждений
$db->enableExceptions(true);
База в памяти:
$db = new SQLite3(':memory:');
SELECT: выборка данных
Через PDO
<?php
// Все записи
$stmt = $pdo->query('SELECT * FROM users');
$users = $stmt->fetchAll(); // массив ассоциативных массивов
// С параметром (защита от SQL-инъекций)
$stmt = $pdo->prepare('SELECT * FROM users WHERE city = :city AND age > :age');
$stmt->execute([':city' => 'Москва', ':age' => 18]);
$users = $stmt->fetchAll();
// Одна запись
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([$id]);
$user = $stmt->fetch();
Через SQLite3
<?php
// Все записи
$result = $db->query('SELECT * FROM users');
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
echo $row['name'] . "\n";
}
// С параметром
$stmt = $db->prepare('SELECT * FROM users WHERE city = :city');
$stmt->bindValue(':city', 'Москва', SQLITE3_TEXT);
$result = $stmt->execute();
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
var_dump($row);
}
INSERT, UPDATE, DELETE
INSERT через PDO
<?php
$stmt = $pdo->prepare(
'INSERT INTO users (name, email, city) VALUES (:name, :email, :city)'
);
$stmt->execute([
':name' => 'Алексей',
':email' => 'alex@example.com',
':city' => 'Москва',
]);
$lastId = $pdo->lastInsertId(); // ID вставленной записи
UPDATE и DELETE через PDO
<?php
// UPDATE
$stmt = $pdo->prepare('UPDATE users SET city = :city WHERE id = :id');
$stmt->execute([':city' => 'СПб', ':id' => 5]);
$affected = $stmt->rowCount(); // количество затронутых строк
// DELETE
$stmt = $pdo->prepare('DELETE FROM users WHERE id = :id');
$stmt->execute([':id' => 5]);
INSERT через SQLite3
<?php
$stmt = $db->prepare(
'INSERT INTO users (name, email) VALUES (:name, :email)'
);
$stmt->bindValue(':name', 'Мария', SQLITE3_TEXT);
$stmt->bindValue(':email', 'maria@example.com', SQLITE3_TEXT);
$stmt->execute();
$lastId = $db->lastInsertRowID();
Создание таблиц из PHP
<?php
// PDO — создать таблицу если не существует
$pdo->exec('
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE,
city TEXT,
created_at TEXT DEFAULT (datetime("now"))
)
');
// SQLite3
$db->exec('
CREATE TABLE IF NOT EXISTS products (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
price REAL,
stock INTEGER DEFAULT 0
)
');
Транзакции: массовая вставка данных
Транзакции критически важны при массовой вставке. Без транзакции SQLite делает fsync на каждый INSERT — это катастрофически медленно. В транзакции 10 000 записей вставляются в 100–300 раз быстрее.
<?php
// PDO — вставка 10 000 строк в транзакции
$pdo->beginTransaction();
try {
$stmt = $pdo->prepare('INSERT INTO log (message, created_at) VALUES (?, ?)');
for ($i = 0; $i < 10000; $i++) {
$stmt->execute(["Запись $i", date('Y-m-d H:i:s')]);
}
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
throw $e;
}
<?php
// SQLite3 — то же самое
$db->exec('BEGIN TRANSACTION');
$stmt = $db->prepare('INSERT INTO log (message) VALUES (:msg)');
for ($i = 0; $i < 10000; $i++) {
$stmt->bindValue(':msg', "Запись $i", SQLITE3_TEXT);
$stmt->execute();
$stmt->reset();
}
$db->exec('COMMIT');
Результат: 10 000 записей без транзакции — ~30 секунд. В транзакции — ~0.1 секунды.
PHP SQLite ORM: ORM::for_table и альтернативы
Популярный минималистичный ORM для PHP — Paris/Idiorm. Именно его методы ORM::for_table() и ORM::close() чаще всего ищут разработчики.
Установка Idiorm через Composer
composer require j4mie/idiorm
Подключение к SQLite
<?php
require 'vendor/autoload.php';
ORM::configure('sqlite:' . __DIR__ . '/database.db');
ORM::for_table() — основные операции
<?php
// SELECT — все записи
$users = ORM::for_table('users')->find_many();
foreach ($users as $user) {
echo $user->name . "\n";
}
// SELECT — с условием
$user = ORM::for_table('users')
->where('email', 'alex@example.com')
->find_one();
// SELECT — несколько условий
$results = ORM::for_table('products')
->where('category', 'Книги')
->where_gt('price', 500)
->order_by_asc('price')
->find_many();
// INSERT
$user = ORM::for_table('users')->create();
$user->name = 'Алексей';
$user->email = 'alex@example.com';
$user->save();
// UPDATE
$user = ORM::for_table('users')->find_one(5);
$user->city = 'Москва';
$user->save();
// DELETE
$user = ORM::for_table('users')->find_one(5);
$user->delete();
ORM::close() — закрытие соединения
<?php
// Явно закрыть соединение (например в CLI-скриптах)
ORM::get_db()->close(); // через PDO
// или через сброс конфигурации:
ORM::reset_config();
ORM::reset_db();
Примечание: в веб-запросах закрывать соединение вручную не нужно — PHP закрывает его автоматически по завершении скрипта.
Альтернативы Idiorm для SQLite
| ORM | Размер | Особенность |
|---|---|---|
| Idiorm/Paris | Микро | Минималистичный, только Active Record |
| Eloquent (Laravel) | Средний | Полноценный ORM, работает вне Laravel через illuminate/database |
| RedBeanPHP | Средний | Создаёт таблицы автоматически при первой вставке |
| Doctrine DBAL | Большой | Промышленный ORM, избыточен для SQLite-проектов |
Оптимизация производительности PHP + SQLite
SQLite работает быстро «из коробки», но несколько настроек дают кратный прирост производительности.
1. WAL-режим — ускорить параллельное чтение
<?php
// Включить WAL сразу после подключения
$pdo->exec('PRAGMA journal_mode = WAL');
// WAL позволяет одновременно читать и писать в БД
// По умолчанию: DELETE journal — блокирует чтение при записи
2. Кеш в памяти — ускорить чтение
<?php
// Размер кеша страниц: 64 МБ (по умолчанию ~2 МБ)
$pdo->exec('PRAGMA cache_size = -64000'); // отрицательное число = КБ
// Хранить временные таблицы в памяти
$pdo->exec('PRAGMA temp_store = MEMORY');
3. Индексы — ускорить SELECT
<?php
// Создать индекс на часто используемое поле
$pdo->exec('CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)');
$pdo->exec('CREATE INDEX IF NOT EXISTS idx_orders_status ON orders(status)');
// Проверить план выполнения запроса
$stmt = $pdo->query('EXPLAIN QUERY PLAN SELECT * FROM users WHERE email = "x@x.com"');
var_dump($stmt->fetchAll());
4. Synchronous OFF — для некритичных данных
<?php
// Отключить синхронизацию с диском (быстро, но риск потери данных при краше ОС)
// Подходит для: логи, кеш, временные данные
$pdo->exec('PRAGMA synchronous = OFF');
// Для продакшн-данных оставьте NORMAL (по умолчанию)
5. Итоговый набор PRAGMA для PHP-проекта
<?php
function connectSQLite(string $path): PDO {
$pdo = new PDO('sqlite:' . $path);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
// Оптимальные настройки для большинства PHP-проектов
$pdo->exec('PRAGMA journal_mode = WAL'); // параллельное чтение/запись
$pdo->exec('PRAGMA cache_size = -32000'); // 32 МБ кеша
$pdo->exec('PRAGMA temp_store = MEMORY'); // временные таблицы в RAM
$pdo->exec('PRAGMA synchronous = NORMAL'); // баланс скорость/надёжность
return $pdo;
}
Удалённый доступ к SQLite через PHP
SQLite — встраиваемая база данных без сервера, поэтому прямого сетевого подключения у неё нет. Удалённый доступ реализуется через PHP-скрипт как HTTP-API.
Вариант 1 — простой REST API на чистом PHP
<?php
// api.php — простой HTTP-API для чтения из SQLite
// Защита: токен в заголовке Authorization
define('API_TOKEN', 'ваш-секретный-токен');
define('DB_PATH', __DIR__ . '/database.db');
header('Content-Type: application/json; charset=utf-8');
// Проверка токена
$token = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
if ($token !== 'Bearer ' . API_TOKEN) {
http_response_code(401);
echo json_encode(['error' => 'Unauthorized']);
exit;
}
$pdo = new PDO('sqlite:' . DB_PATH);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$action = $_GET['action'] ?? '';
switch ($action) {
case 'users':
$stmt = $pdo->query('SELECT id, name, city FROM users ORDER BY id DESC LIMIT 100');
echo json_encode($stmt->fetchAll());
break;
case 'user':
$id = (int)($_GET['id'] ?? 0);
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([$id]);
echo json_encode($stmt->fetch() ?: null);
break;
default:
http_response_code(400);
echo json_encode(['error' => 'Unknown action']);
}
Вызов из другого сервера:
curl -H "Authorization: Bearer ваш-секретный-токен" \
"https://ваш-сайт.ru/api.php?action=users"
Вариант 2 — PHPLiteAdmin (веб-интерфейс)
PHPLiteAdmin — однофайловый веб-интерфейс для SQLite, аналог phpMyAdmin. Загрузите phpliteadmin.php на сервер, установите пароль в начале файла и откройте в браузере.
<?php
// Настройки в начале phpliteadmin.php
$password = 'ваш_пароль'; // обязательно измените!
$directory = './'; // папка с .db файлами
$allowed_extensions = ['db', 'sqlite', 'sqlite3'];
Важно: закройте доступ к PHPLiteAdmin по IP или через .htaccess после использования. Не оставляйте его открытым на продакшн-сервере.
Практический пример: сохранение заявок с лендинга
Типичный сценарий: форма на лендинге сохраняет заявки в SQLite. Никакого MySQL, никакой настройки сервера — файл leads.db рядом с проектом.
<?php
// leads.php — обработчик формы
define('DB_PATH', __DIR__ . '/data/leads.db');
function getDb(): PDO {
$pdo = new PDO('sqlite:' . DB_PATH);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('PRAGMA journal_mode = WAL');
$pdo->exec('
CREATE TABLE IF NOT EXISTS leads (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
phone TEXT,
email TEXT,
source TEXT,
created_at TEXT DEFAULT (datetime("now", "localtime"))
)
');
return $pdo;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim(strip_tags($_POST['name'] ?? ''));
$phone = trim(strip_tags($_POST['phone'] ?? ''));
$email = trim(strip_tags($_POST['email'] ?? ''));
if ($name === '') {
http_response_code(400);
echo json_encode(['error' => 'Имя обязательно']);
exit;
}
$pdo = getDb();
$stmt = $pdo->prepare(
'INSERT INTO leads (name, phone, email, source) VALUES (?, ?, ?, ?)'
);
$stmt->execute([$name, $phone, $email, $_SERVER['HTTP_REFERER'] ?? '']);
header('Content-Type: application/json');
echo json_encode(['ok' => true, 'id' => $pdo->lastInsertId()]);
exit;
}
Просмотр накопленных заявок:
<?php
// admin-leads.php — простой просмотр заявок (закройте Basic Auth!)
$pdo = new PDO('sqlite:' . __DIR__ . '/data/leads.db');
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$leads = $pdo->query('SELECT * FROM leads ORDER BY created_at DESC')->fetchAll();
foreach ($leads as $lead) {
echo "{$lead['created_at']} | {$lead['name']} | {$lead['phone']}\n";
}
Когда SQLite не подходит для PHP-проекта
SQLite отлично работает в PHP, но есть сценарии где лучше выбрать MySQL или PostgreSQL:
- Высокая конкурентная запись — SQLite блокирует запись на уровне файла. При 50+ одновременных записях появятся ошибки
SQLITE_BUSY. Решение: WAL-режим снижает проблему, но не устраняет полностью. - Несколько серверов — SQLite-файл должен быть на одном сервере. Если у вас балансировщик нагрузки с несколькими PHP-серверами — нужна сетевая СУБД.
- Размер базы больше 10 ГБ — SQLite поддерживает до 281 ТБ технически, но производительность деградирует. При размере больше 10 ГБ рассмотрите миграцию на PostgreSQL.
- Сложные права доступа — SQLite не поддерживает пользователей и роли на уровне БД.
SQLite идеален для PHP когда: лендинг/портфолио, парсер, кеш, CLI-утилита, прототип, тесты, небольшое API до 10 000 запросов/сутки.




Благодарю! Несколько недель искал и не мог найти примеры — а тут всё подробно. Делаю Аналитикуна сайт и в библиотеку базу книг на SQLite.