定制 mongoose-studio/phobos-framework-database-sqlite 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

mongoose-studio/phobos-framework-database-sqlite

Composer 安装命令:

composer require mongoose-studio/phobos-framework-database-sqlite

包简介

Phobos Framework SQLite Connector for Database Layer

README 文档

README

PHP Version License Phobos Framework

Phobos Framework

Driver SQLite para Phobos Framework Database Layer. Cero configuración de servidor: conecta a un archivo .sqlite o a una base de datos en memoria (:memory:), con las claves foráneas activadas por defecto y los PRAGMAs más útiles expuestos como opciones de conexión.

Es el driver ideal para tests (SQLite en memoria, rápido y aislado), prototipos y aplicaciones de escritorio o embebidas.

Características

  • 🪶 Sin servidor - Un archivo o :memory:, sin host, puerto ni credenciales
  • 🔒 Foreign keys activas por defecto - SQLite las trae apagadas; este driver las enciende
  • PRAGMAs comunes - journal_mode (WAL), busy_timeout, synchronous
  • 🎯 Savepoints - Transacciones anidadas completas
  • 🧪 Ideal para testing - :memory: da una BD limpia por proceso
  • 🛡️ Valores validados - Los PRAGMAs pasan por lista blanca para evitar inyección
  • 🏷️ Identificadores estándar - Citado con comillas dobles

Instalación

composer require mongoose-studio/phobos-framework-database-sqlite

Dependencias

Este driver requiere:

  • mongoose-studio/phobos-framework ^3.1
  • mongoose-studio/phobos-framework-database ^3.2
  • Extensión ext-pdo habilitada
  • Extensión ext-pdo_sqlite habilitada

Configuración

1. Registrar el Driver

En tu config/database.php:

<?php

return [
    'default' => 'sqlite',

    'drivers' => [
        'sqlite' => PhobosFramework\Database\Drivers\SQLite\SQLiteDriver::class,
    ],

    'connections' => [
        'sqlite' => [
            'driver' => 'sqlite',
            'database' => storage_path('database/app.sqlite'),
            'foreign_keys' => true,
            'journal_mode' => 'WAL',
        ],
    ],
];

2. Variables de Entorno

En tu archivo .env:

DB_CONNECTION=sqlite
DB_DATABASE=/ruta/absoluta/a/database/app.sqlite

Opciones de Configuración

A diferencia de MySQL, SQLite no usa host, port, username, password, charset ni collation. La única opción obligatoria es database.

database (obligatorio)

'sqlite' => [
    'driver' => 'sqlite',
    'database' => '/var/data/app.sqlite',  // Ruta al archivo
    // 'database' => ':memory:',            // Base de datos en memoria
]
Valor Resultado
Ruta a un archivo sqlite:/var/data/app.sqlite — persiste en disco
:memory: sqlite::memory: — vive en RAM, se pierde al cerrar la conexión

Nota sobre :memory:: cada conexión PDO nueva crea una base de datos en memoria independiente. Mientras reutilices la misma conexión (como hace el ConnectionManager), los datos persisten durante todo el proceso — perfecto para una suite de tests.

foreign_keys (por defecto true)

SQLite trae las claves foráneas desactivadas por defecto (una de las trampas más comunes del motor). Este driver las activa salvo que lo indiques explícitamente:

'sqlite' => [
    // ...
    'foreign_keys' => true,   // Default. Ejecuta PRAGMA foreign_keys = ON
    // 'foreign_keys' => false, // Desactiva las restricciones FK
]

journal_mode

Controla el modo de journaling. WAL (Write-Ahead Logging) suele ser la mejor opción para concurrencia:

'sqlite' => [
    // ...
    'journal_mode' => 'WAL',
]

Valores válidos: DELETE, TRUNCATE, PERSIST, MEMORY, WAL, OFF.

  • WAL - Mejor concurrencia (lectores no bloquean al escritor). Recomendado para archivos.
  • MEMORY - Journal en RAM, más rápido pero menos seguro ante caídas.
  • DELETE - Comportamiento clásico por defecto de SQLite.

busy_timeout

Milisegundos que SQLite espera ante un bloqueo antes de devolver SQLITE_BUSY:

'sqlite' => [
    // ...
    'busy_timeout' => 5000,  // Espera hasta 5 segundos
]

synchronous

Nivel de sincronización con disco. Compromiso entre durabilidad y velocidad:

'sqlite' => [
    // ...
    'synchronous' => 'NORMAL',
]

Valores válidos: OFF, NORMAL, FULL, EXTRA (o sus equivalentes numéricos 0, 1, 2, 3).

  • FULL - Máxima durabilidad (default de SQLite).
  • NORMAL - Buen equilibrio, recomendado con WAL.
  • OFF - El más rápido, pero puede corromper datos ante un corte de energía.

Opciones PDO Adicionales

'sqlite' => [
    // ...
    'options' => [
        PDO::ATTR_TIMEOUT => 5,
    ],
]

Características Específicas de SQLite

Identificadores con Comillas Dobles

El driver usa comillas dobles para identificadores (el estándar SQL):

// quoteIdentifier() genera:
"users"
"weird ""column"""   // escapa comillas dobles internas

SQLite también acepta backticks (por compatibilidad con MySQL), por lo que el Query Builder del núcleo funciona sin cambios sobre este driver.

Transacciones Anidadas (Savepoints)

SQLite soporta savepoints, así que las transacciones anidadas del TransactionManager funcionan igual que en MySQL:

$tm = db()->getTransactionManager();

$tm->begin();                    // BEGIN
try {
    // ... operaciones ...

    $sp = $tm->begin();          // SAVEPOINT anidado
    try {
        // ... más operaciones ...
        $tm->commit($sp);        // RELEASE SAVEPOINT
    } catch (Exception $e) {
        $tm->rollback($sp);      // ROLLBACK TO SAVEPOINT (solo lo anidado)
    }

    $tm->commit();               // COMMIT de la transacción externa
} catch (Exception $e) {
    $tm->rollback();             // ROLLBACK completo
}

Niveles de Aislamiento

SQLite es SERIALIZABLE de forma nativa. A diferencia de MySQL, no soporta READ COMMITTED ni REPEATABLE READ. Lo único que puede relajarse es a READ UNCOMMITTED (y solo tiene efecto en modo shared-cache):

$driver = new SQLiteDriver();

$driver->getSetIsolationLevelSQL('SERIALIZABLE');      // PRAGMA read_uncommitted = 0
$driver->getSetIsolationLevelSQL('READ UNCOMMITTED');  // PRAGMA read_uncommitted = 1

$driver->getSetIsolationLevelSQL('READ COMMITTED');    // ❌ InvalidArgumentException
$driver->getSetIsolationLevelSQL('REPEATABLE READ');   // ❌ InvalidArgumentException

Pedir un nivel que SQLite no soporta lanza una InvalidArgumentException explícita, en vez de generar SQL inválido silenciosamente.

Ejemplos de Uso

Testing (SQLite en memoria)

La configuración de oro para una suite de tests: rápida, aislada y sin dejar rastro en disco.

'sqlite_test' => [
    'driver' => 'sqlite',
    'database' => ':memory:',
    'foreign_keys' => true,
]
use PhobosFramework\Database\Connection\ConnectionManager;
use PhobosFramework\Database\Drivers\SQLite\SQLiteDriver;

$manager = ConnectionManager::getInstance();
$manager->registerDriver('sqlite', new SQLiteDriver());
$manager->addConnection('default', [
    'driver' => 'sqlite',
    'database' => ':memory:',
]);
$manager->setDefaultConnection('default');

// Crear el esquema una vez y ejercitar tus entidades contra él
$manager->getConnection()->getPDO()->exec('
    CREATE TABLE users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        email TEXT NOT NULL
    )
');

Aplicación con archivo persistente

'sqlite' => [
    'driver' => 'sqlite',
    'database' => storage_path('database/app.sqlite'),
    'foreign_keys' => true,
    'journal_mode' => 'WAL',       // Mejor concurrencia
    'synchronous' => 'NORMAL',     // Equilibrio con WAL
    'busy_timeout' => 5000,        // Tolera bloqueos breves
]

Arquitectura

Estructura del Driver

SQLiteDriver
    ├── getDSN()                   - Construye el DSN (archivo o :memory:)
    ├── getPDOOptions()            - Opciones PDO seguras (heredadas de AbstractDriver)
    ├── configure()               - Aplica PRAGMAs post-conexión
    ├── getName()                 - Retorna 'sqlite'
    ├── supportsSavepoints()      - Retorna true
    ├── quoteIdentifier()         - Envuelve en comillas dobles
    ├── getSetIsolationLevelSQL() - SERIALIZABLE / READ UNCOMMITTED (vía PRAGMA)
    └── getLastInsertId()         - ROWID de la última inserción (ignora la secuencia)

Proceso de Conexión

  1. DSN Generation: getDSN() construye la cadena

    • Archivo: sqlite:/ruta/a/app.sqlite
    • Memoria: sqlite::memory:
  2. PDO Creation: Se crea la instancia PDO con las opciones seguras por defecto (modo de error por excepción, fetch asociativo, prepares nativos).

  3. Post-Connection Config: configure() ejecuta los PRAGMAs

    • PRAGMA foreign_keys (ON por defecto)
    • PRAGMA journal_mode si se configuró
    • PRAGMA busy_timeout si se configuró
    • PRAGMA synchronous si se configuró

Compatibilidad

  • SQLite 3.x (vía ext-pdo_sqlite)
  • Soporte completo de savepoints y claves foráneas (SQLite 3.6.19+)
  • WAL disponible desde SQLite 3.7.0+

🐛 Troubleshooting

Las claves foráneas no se respetan

Si esperabas que un INSERT con una FK inválida fallara y no lo hace, revisa que no hayas puesto 'foreign_keys' => false. Recuerda que SQLite las trae apagadas por defecto: este driver las activa, pero solo si no las desactivas explícitamente.

SQLSTATE[HY000]: database is locked

SQLite bloquea el archivo completo durante una escritura. Mitiga con:

'journal_mode' => 'WAL',   // Lectores no bloquean al escritor
'busy_timeout' => 5000,    // Espera en vez de fallar de inmediato

unable to open database file

SQLSTATE[HY000] [14] unable to open database file
  • Verifica que el directorio del archivo exista (SQLite crea el archivo, no las carpetas).
  • Verifica permisos de escritura en el directorio.
  • Usa una ruta absoluta para evitar sorpresas con el directorio de trabajo.

Los datos de :memory: desaparecen entre partes del código

Cada conexión PDO nueva a :memory: es una base distinta. Asegúrate de reutilizar la misma conexión (el ConnectionManager la cachea). No abras un PDO nuevo esperando ver los datos de otro.

Licencia

Este proyecto está licenciado bajo la Licencia MIT - ver el archivo LICENSE para más detalles.

Autor

Marcel Rojas
marcelrojas16@gmail.com
Mongoose Studio

Contribuciones

Las contribuciones son bienvenidas. Por favor:

  1. Fork el proyecto
  2. Crea una rama para tu feature (git checkout -b feature/amazing-feature)
  3. Commit tus cambios (git commit -m 'Add amazing feature')
  4. Push a la rama (git push origin feature/amazing-feature)
  5. Abre un Pull Request

Phobos Framework by Mongoose Studio

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 2
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-07-14

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固