bmob-database-flutter · v0.1.0 · 2026-06-04 · sha256 0bbf159379ad0c53

bmob-database-flutter v0.1.0A

Immutable. This exact content is served forever at /api/v1/blob/0bbf159379ad0c53.

---
name: bmob-database-flutter
description: "Use when implementing Bmob NoSQL database CRUD in a Flutter / Dart project with the official bmob_plugin package. Triggers: flutter pub add bmob_plugin, package:bmob_plugin/bmob_plugin.dart, Bmob.initialize, BmobQuery, BmobObject, BmobUser, BmobFile, BmobGeoPoint, BmobRelation, BmobAcl, BmobError.convert, blog.save(), query.queryObjects(), query.setInclude, Dart Bmob, Flutter Bmob. NOT for JavaScript / Web / Mini Program (use bmob-database-javascript), Android native without Flutter (use bmob-database-android), iOS native without Flutter (use bmob-database-ios), or server-side HTTP only (use bmob-database-restful). If Bmob MCP is configured, call get_project_tables via bmob-mcp before writing code."
metadata:
  author: bmob
  version: "0.1.0"
  sdk: "bmob_plugin"
  sdk_pub: "https://pub.dev/packages/bmob_plugin"
  sdk_repo: "https://github.com/bmob/bmob-flutter-sdk/tree/master/data_plugin"
  demo_repo: "https://github.com/bmob/bmob-flutter-sdk/tree/master/data_demo"
  docs: "https://github.com/bmob/BmobDocs/blob/master/mds/data/flutter/index.md"
  docs_raw: "https://raw.githubusercontent.com/bmob/BmobDocs/master/mds/data/flutter/index.md"
---

# Bmob Database — Flutter / Dart SDK

官方 Flutter 插件 **[`bmob_plugin`](https://pub.dev/packages/bmob_plugin)**(源码 [`bmob-flutter-sdk/data_plugin`](https://github.com/bmob/bmob-flutter-sdk/tree/master/data_plugin))。数据模型 **继承 `BmobObject` + JSON 序列化**(与 Android 类似),查询用泛型 **`BmobQuery<T>`**,异步返回 **`Future`** + `.then` / `.catchError`。

完整 API 以 [BmobDocs Flutter 文档](https://github.com/bmob/BmobDocs/blob/master/mds/data/flutter/index.md) 为准;agent 可直接 WebFetch `metadata.docs_raw`。

## 核心原则

**1. 安装与引用**

```bash
flutter pub add bmob_plugin
```

```dart
import 'package:bmob_plugin/bmob_plugin.dart';
```

**2. 初始化** — 控制台 → 设置 → 应用密钥 → **Secret Key**、**API 安全码**;**不要**在客户端填 `masterKey`(第三个可选参数仅服务端场景)。

```dart
// main() 或 App 启动最早处
Bmob.initialize(secretKey, apiSafe);
// 不推荐:Bmob.initialize(secretKey, apiSafe, masterKey);
```

**3. 上线换备案域名** — `resetDomain` 必须在 `initialize` **之前**(开发期内置测试域名有请求次数限制):

```dart
Bmob.resetDomain("http://api.yourdomain.com");
Bmob.initialize(secretKey, apiSafe);
```

**4. 自定义表模型** — 每张业务表一个 Dart 类 **extends `BmobObject`**,并实现 `fromJson` / `toJson`(见 [`references/model-and-init.md`](references/model-and-init.md))。表名默认与类名一致(如 `Blog` → 表 `Blog`)。

**5. 错误处理** — 统一用 `BmobError.convert(e)` 取 `code` / `error`:

```dart
}).catchError((e) {
  final err = BmobError.convert(e);
  print('${err.code}: ${err.error}');
});
```

**6. 保留字段** — `objectId`、`createdAt`、`updatedAt`、`ACL` 由 SDK / 服务端维护;业务代码在更新 / 删除时必须设置 `objectId`。

## 安全清单

- [ ] **客户端不要传 Master Key** 给 `Bmob.initialize` 第三参数。
- [ ] **Secret Key / API 安全码** 用 `--dart-define`、`.env` + `flutter_dotenv` 或 CI 注入,不要 commit 进 git。
- [ ] **release 前 `resetDomain` 为备案域名**,且顺序在 `initialize` 之前。
- [ ] **写入的表必须配 ACL**(`blog.setAcl(bmobAcl)`),否则任意用户可改任意行。
- [ ] **Android 文件上传 / 下载** 需先适配存储权限(见官方文档「文件操作」)。
- [ ] **实时监听** `RealTimeDataManager` 回调里 `data.data` 是 `Map`,不要直接当 `Blog` 用。

## 常见问题

跨平台 Q&A:[`shared/faq.md`](../../shared/faq.md)(含 Flutter 路由说明)。

## 反模式

见 [`shared/anti-patterns.md`](../../shared/anti-patterns.md)。本端重点:客户端勿传 `masterKey`;实时回调勿直接把 `Map` 当 model。

## 单条 CRUD(以 `Blog` 为例)

```dart
class Blog extends BmobObject {
  String? title;
  String? content;
  int? like;
  BmobUser? author;

  Blog();

  Blog.fromJson(Map<String, dynamic> json) {
    objectId = json['objectId'];
    title = json['title'];
    content = json['content'];
    like = json['like'];
    if (json['author'] != null) {
      author = BmobUser()..objectId = json['author']['objectId'];
    }
  }

  Map<String, dynamic> toJson() => {
        'title': title,
        'content': content,
        'like': like,
        if (author != null) 'author': author,
      };
}
```

### 新增

```dart
final blog = Blog()
  ..title = '博客标题'
  ..content = '博客内容'
  ..like = 77;

blog.save().then((BmobSaved saved) {
  print(saved.objectId);
}).catchError((e) => print(BmobError.convert(e).error));
```

### 查询单条(含 Pointer include)

```dart
final q = BmobQuery<Blog>();
q.setInclude('author');
q.queryObject(objectId).then((data) {
  final blog = Blog.fromJson(data);
  print(blog.title);
}).catchError((e) => print(BmobError.convert(e).error));
```

### 更新

```dart
final blog = Blog()
  ..objectId = objectId
  ..title = '修改标题';
blog.update().then((BmobUpdated u) => print(u.updatedAt));
```

### 删除

```dart
Blog()..objectId = objectId
  ..delete()
  .then((BmobHandled h) => print(h.msg));
```

### 删除某字段值

```dart
Blog()..objectId = objectId
  ..deleteFieldValue('content')
  .then((BmobUpdated u) => print(u.updatedAt));
```

## 条件查询与分页

```dart
final q = BmobQuery<Blog>();
q.addWhereEqualTo('title', '博客标题');
q.addWhereGreaterThan('like', 70);
q.setOrder('-createdAt'); // 逆序:字段前加 -
q.setLimit(10);
q.setSkip(0);
q.queryObjects().then((List<dynamic> data) {
  final blogs = data.map((i) => Blog.fromJson(i)).toList();
});
```

| 比较 | 方法 |
|------|------|
| 等于 | `addWhereEqualTo` |
| 不等于 | `addWhereNotEqualTo` |
| 小于 | `addWhereLessThan` |
| 小于等于 | `addWhereLessThanOrEqualTo` |
| 大于 | `addWhereGreaterThan` |
| 大于等于 | `addWhereGreaterThanOrEqualTo` |
| 条数 | `queryCount()` → `Future<int>` |

OR / AND 复合查询见 [`references/query.md`](references/query.md)。

## Pointer / 关联

```dart
final blog = Blog()..title = '带作者';
final user = BmobUser()..objectId = '已有用户的objectId';
blog.author = user;
blog.save();
// 查询:q.setInclude('author');
// 解除关联:blog.deleteFieldValue('author')
```

详见 [`references/pointer-and-relation.md`](references/pointer-and-relation.md)。

## 用户 / 短信 / 文件(skill 内简表,P1 将有专用 auth/storage)

| 场景 | 入口 |
|------|------|
| 注册 | `BmobUser()..username=.. ..password=..` → `.register()` |
| 用户名密码登录 | `.login()` |
| 短信登录 | `BmobSms.sendSms()` → `loginBySms(code)` |
| 上传文件 | `BmobFileManager.upload(file)` → 写入表的 `BmobFile` 字段 |

完整片段见 [Flutter 文档「用户操作」「文件操作」](https://github.com/bmob/BmobDocs/blob/master/mds/data/flutter/index.md)。

## 与 MCP 联动

如已配置 [Bmob MCP](../bmob-mcp/SKILL.md),写 Flutter 代码前先 `get_project_tables`,避免 schemaless 下字段名拼错、Pointer 格式错误。

## 排错速查

跨平台现象先查 [`shared/faq.md`](../../shared/faq.md)。

| 现象 | 排查 |
|------|------|
| 初始化后请求失败 | Secret Key / API 安全码是否与控制台一致;是否忘记 release 的 `resetDomain` |
| 更新 / 删无效 | 未设 `objectId` |
| include 后 author 为空 | `setInclude` 字段名与表字段一致;Pointer 目标 objectId 存在 |
| `BmobError` code 不明 | [`bmob-error-codes`](../bmob-error-codes/SKILL.md) + REST/Android 表对照 |
| 实时监听类型错 | `onDataChanged` 里用 `Map`,勿直接 `Blog.fromJson` 整包 |

## 进阶能力(按需读 references/)

| 主题 | 路径 |
|------|------|
| 端到端场景 | [`shared/recipes/`](../../shared/recipes/) |
| BmobDocs 同步代码片段 | [`references/snippets/`](references/snippets/) |
| 模型继承 + JSON 序列化 | [`references/model-and-init.md`](references/model-and-init.md) |
| 条件 / OR·AND / 统计 / 个数查询 | [`references/query.md`](references/query.md) |
| Pointer / Relation / ACL / 角色 | [`references/pointer-and-relation.md`](references/pointer-and-relation.md) |

## 参考

- 完整 API:[mds/data/flutter/index.md](https://github.com/bmob/BmobDocs/blob/master/mds/data/flutter/index.md)
- Raw(agent fetch):`metadata.docs_raw`
- 插件源码:<https://github.com/bmob/bmob-flutter-sdk/tree/master/data_plugin>
- 示例工程:<https://github.com/bmob/bmob-flutter-sdk/tree/master/data_demo>
- 操作路由:[`shared/operation-routing.md`](../../shared/operation-routing.md)
- 错误码:[`bmob-error-codes`](../bmob-error-codes/SKILL.md)
- MCP:[`bmob-mcp`](../bmob-mcp/SKILL.md)