ThinkPHP6连接SQLite必须同时满足四个硬性条件:DSN格式为sqlite:/absolute/path/to/db.db、安装topthink/think-sqlite扩展、确保数据库文件路径绝对且可写、CLI与Web环境配置完全一致,缺一不可。

ThinkPHP6 连接 SQLite 不是“配对 type 就行”,而是必须同时满足 DSN 格式、扩展安装、路径权限、CLI/Web 一致性这四个硬性条件,缺一不可。
DSN 必须写成 sqlite:/absolute/path/to/db.db,不能省略前缀或用相对路径
ThinkPHP 6 的 PDO SQLite 驱动只靠 dsn 字符串开头的 sqlite: 来识别协议类型。如果只写 'database' => 'runtime/app.db' 或 'dsn' => '/var/www/runtime/app.db',框架会当成 MySQL 默认驱动处理,报错 SQLSTATE[HY000] Unable to open database file。
-
dsn值必须是完整 URI 形式:sqlite:/absolute/path/to/app.db(注意是单斜杠,不是双斜杠,也不是反斜杠) - Windows 下也强制用正斜杠,
runtime\app.db会被解析失败 - 绝对路径是刚需 ——
./runtime/app.db在 CLI 下可能指向public/目录,在 Web 下又指向其他位置,行为不一致 - 推荐拼接方式:
'dsn' => 'sqlite:' . realpath(__DIR__ . '/../runtime/db/app.db'),确保路径真实存在且可写
必须安装 topthink/think-sqlite 扩展,仅启用 pdo_sqlite 不够
PHP 系统级支持 pdo_sqlite(可通过 php -m | grep sqlite 验证),但 ThinkPHP 6 默认不带 SQLite 适配器。没装扩展时,启动直接报错 Driver [sqlite] not supported。
- 执行
composer require topthink/think-sqlite(不是think-orm自带的那套) - 确认
config/database.php中'type' => 'sqlite'与'dsn'同时存在,二者缺一不可 -
hostname、username、password等字段必须留空或删除 —— SQLite 不接受这些参数,残留可能触发无效绑定
并发写入必设 PDO::ATTR_TIMEOUT,否则频繁报 database is locked
SQLite 文件锁机制在高频率请求下极易触发阻塞,ThinkPHP 默认连接池为 1 且无超时配置,导致 AJAX 提交或表单重复点击立刻卡死。
立即学习“PHP免费学习笔记(深入)”;
- 在数据库配置中加入:
'params' => [PDO::ATTR_TIMEOUT => 5](单位秒,别填毫秒) - 避免在事务外做耗时操作(如调外部 API、生成 PDF),否则锁持有时间远超预期
- 高频写场景优先用批量插入:
INSERT INTO table VALUES (),(),(),减少锁竞争次数 - 切勿把
.db文件放在public/目录下 —— Web 服务器可能直接暴露文件内容,且权限更难控制
迁移命令 php think migrate:run 只读 config/database.php,和 .env 无关
常见错误:改了 .env 里的 DB_DATABASE=app.db,但 config/database.php 里仍是 :memory: 或旧路径,结果迁移建表成功,业务查询却提示 no such table —— 因为连的根本不是同一个文件。
- 迁移命令完全忽略
.env,只认config/database.php中'connections'['sqlite']['dsn']的值 - 调试时加一句:
php -r "var_dump(config('database.connections.sqlite.dsn'));",确认 CLI 环境真读到了预期路径 - 多环境配置(如
database_dev.php)需确保APP_ENV=dev生效,否则仍走默认配置 -
:memory:仅限调试,生产环境必须用持久化文件路径,否则每次请求都是空库
最易被忽略的是 CLI 和 Web 两套环境路径解析不一致,以及 think-sqlite 扩展缺失 —— 这两个点不解决,其他配置全对也连不上。



















