写个小工具、做个内部系统,数据量不大但总得存点什么。开个 MySQL 觉得太重,用 SQLite 又不想写 SQL。SleekDB 就是给这种场景准备的:一个 PHP 文件就能搞定所有 CRUD,数据直接存成 JSON。

安装
composer require rakibtg/sleekdb
要求 PHP >= 8.4(PHP 7.x 用 v2.15),需要 ext-json 和 ext-mbstring,基本是标配。

基本使用
SleekDB 的核心概念是 Store(存储),相当于 MySQL 的表或 MongoDB 的集合。每个 Store 就是一个目录,里面的每条数据是一个 JSON 文件。
use SleekDB\Store;
// 数据存储目录(自动创建)
$dataDir = __DIR__ . '/database';
// 创建一个 Store(类似建表)
$users = new Store('users', $dataDir);
// 插入数据(返回的数据会带上自动生成的 _id)
$user = $users->insert([
'name' => 'augushong',
'email' => 'augushong@example.com',
'role' => 'admin',
]);
// $user['_id'] => 1
// 查询全部
$allUsers = $users->findAll();
就这么简单。没有连接字符串、没有迁移脚本、没有 ORM 配置。插入的是数组,查出来的也是数组。

条件查询
SleekDB 通过链式查询构建器实现条件过滤,注意条件以数组形式传入:
use SleekDB\Store;
$articles = new Store('articles', $dataDir);
// 基础条件查询:where 接收 [字段, 操作符, 值] 数组
$results = $articles->createQueryBuilder()
->where(['status', '=', 'published'])
->getQuery()
->fetch();
// 多条件 AND(链式调用 where)
$results = $articles->createQueryBuilder()
->where(['category', '=', 'php'])
->where(['status', '=', 'published'])
->where(['views', '>', 100])
->getQuery()
->fetch();
// OR 条件
$results = $articles->createQueryBuilder()
->where(['category', '=', 'php'])
->orWhere(['category', '=', 'javascript'])
->getQuery()
->fetch();
// IN / NOT IN
$results = $articles->createQueryBuilder()
->in('id', [1, 3, 5, 7])
->getQuery()
->fetch();
// 排序 + 分页
$results = $articles->createQueryBuilder()
->where(['status', '=', 'published'])
->orderBy(['created_at' => 'desc'])
->limit(10)
->skip(0)
->getQuery()
->fetch();
嵌套属性查询
这是 SleekDB 的亮点之一。因为是无模式的文档数据库,数据可以任意嵌套,查询时用点号路径就能深入到嵌套字段:
// 插入带嵌套结构的数据
$articles->insert([
'title' => 'SleekDB 入门',
'author' => [
'name' => 'augushong',
'role' => 'admin'
],
'tags' => ['php', 'nosql', 'database'],
]);
// 直接按嵌套字段查询(点号路径)
$results = $articles->createQueryBuilder()
->where(['author.role', '=', 'admin']) // 查 author.role === admin
->getQuery()
->fetch();
// 数组内元素匹配(contains 操作符)
$results = $articles->createQueryBuilder()
->where(['tags', 'contains', 'php']) // tags 数组中包含 php
->getQuery()
->fetch();
不需要 JOIN,不需要关联表,数据怎么存的就怎么查。
模糊搜索和文本匹配
// LIKE 模糊匹配(支持 % 和 _ 通配符)
$results = $articles->createQueryBuilder()
->where(['title', 'like', '%PHP%'])
->getQuery()
->fetch();
// 全文搜索(指定搜索字段和关键词)
$results = $articles->search(['title', 'content'], 'SleekDB 教程');
// BETWEEN 范围查询
$results = $articles->createQueryBuilder()
->where(['views', 'between', [100, 1000]])
->getQuery()
->fetch();
更新和删除
// 按 ID 更新(返回更新后的完整数据)
$updated = $articles->updateById($articleId, [
'title' => '新标题',
'status' => 'published',
]);
// 批量更新:把所有草稿标记为归档
$count = $articles->createQueryBuilder()
->where(['status', '=', 'draft'])
->getQuery()
->update(['status' => 'archived']);
// 按 ID 删除
$articles->deleteById($articleId);
// 条件删除:删除所有浏览量为 0 的文章
$articles->createQueryBuilder()
->where(['views', '=', 0])
->getQuery()
->delete();
// 查找单条记录(按条件取第一条)
$firstAdmin = $users->findOneBy(['role', '=', 'admin']);
投影和去重
// 只选取指定字段(减少传输量)
$results = $articles->createQueryBuilder()
->select(['title', 'author.name', 'created_at'])
->getQuery()
->fetch();
// 排除某些字段(比如排除大段正文内容)
$results = $articles->createQueryBuilder()
->except(['content', 'raw_html'])
->getQuery()
->fetch();
// 字段去重
$categories = $articles->createQueryBuilder()
->distinct('category')
->getQuery()
->fetch();
// 统计数量
$count = count($articles->createQueryBuilder()
->where(['status', '=', 'published'])
->getQuery()
->fetch());
缓存机制
SleekDB 默认开启自动缓存。每次查询结果会被缓存到文件,后续相同查询直接读缓存文件,不再遍历所有 JSON 数据:
// 默认行为:自动缓存,insert/update/delete 时自动失效
$results = $articles->findAll(); // 第一次遍历文件,之后走缓存
// 手动控制缓存
$results = $articles->createQueryBuilder()
->disableCache() // 本次查询不使用缓存
->getQuery()
->fetch();
$results = $articles->createQueryBuilder()
->useCache(3600) // 缓存 1 小时
->getQuery()
->fetch();
$results = $articles->createQueryBuilder()
->regenerateCache() // 强制刷新缓存
->getQuery()
->fetch();
初始化 Store 时也可以全局配置缓存策略:
$config = [
'auto_cache' => true, // 是否启用自动缓存(默认 true)
'cache_lifetime' => null, // 缓存有效期(秒),null 表示永不过期
'primary_key' => '_id', // 主键字段名
];
$articles = new Store('articles', $dataDir, $config);
数据存储结构
看一下 SleekDB 实际在磁盘上存了什么:
database/
├── users/ # 一个 Store 就是一个目录
│ ├── data/ # 每条记录一个 JSON 文件
│ │ ├── 1.json # _id 为 1 的用户
│ │ ├── 2.json
│ │ └── 3.json
│ ├── cache/ # 查询缓存文件
│ │ └── abc123.no_lifetime.json
│ └── _cnt.sdb # 自增计数器
└── articles/
├── data/
│ └── 1.json
└── cache/
└── def456.json
每条记录就是一个独立的 JSON 文件,人类可读、随时可以备份迁移。

适用场景和不适用场景
SleekDB 适合:
- 个人博客、小型 CMS、后台管理工具
- 不想配置数据库服务的环境(共享主机、Docker 容器内轻应用)
- 原型开发和快速验证想法
- 几 GB 以内的数据量,读写频率中等以下
不适合:
- 高并发写入场景(没有事务支持,并发写入可能冲突)
- 需要复杂关系查询的系统(没有 JOIN,虽然能模拟但不优雅)
- 数据量超过几 GB 的场景(全量扫描性能下降明显)
- 需要强一致性和事务保证的业务
如果你需要一个"比数组持久化、比 MySQL 轻得多"的方案,SleekDB 就是答案。
原文标题: [rakibtg/sleekdb]纯 PHP 实现的零依赖 NoSQL 扁平文件数据库
原文地址: https://phpreturn.com/index/a69f5f9f0498ce.html
原文平台: PHP武器库
版权声明: 本文由phpreturn.com(PHP武器库官网)原创和首发,所有权利归phpreturn(PHP武器库)所有,本站允许任何形式的转载/引用文章,但必须同时注明出处。