Skip to content

5.10 字典模块 ​

概述

DictService 提供字典项的读取、正反向转换与缓存管理,是字典体系的核心服务。采用两级缓存(请求级 + 持久缓存),同一请求内不重复查库,跨请求复用持久缓存。

字典体系架构 ​

text
┌─────────────────────────────────────────────────────────────────────┐
│                         字典体系                                     │
│                                                                     │
│  ┌──────────────────┐    ┌──────────────────┐                      │
│  │ think_dict       │    │ think_dict_item  │                      │
│  │ 字典主表         │    │ 字典项表         │                      │
│  │                  │    │                  │                      │
│  │ id               │◄───│ dict_id          │                      │
│  │ name (字典名称)  │    │ name (项名称)    │                      │
│  │ code (字典编码)  │    │ value (项值)     │                      │
│  │ remark           │    │ sort (排序)      │                      │
│  └──────────────────┘    │ note (备注)      │                      │
│                          └──────────────────┘                      │
│                                                                     │
│  ┌──────────────────┐    ┌──────────────────┐                      │
│  │ DictService      │    │ Logic 层         │                      │
│  │ 字典服务         │    │ serializeMaps    │                      │
│  │                  │    │ 自动翻译         │                      │
│  │ getText()        │    │                  │                      │
│  │ getValue()       │◄───│ 'status' =>      │                      │
│  │ getOptions()     │    │   'user_status'  │                      │
│  │ clearCache()     │    │                  │                      │
│  └──────────────────┘    └──────────────────┘                      │
└─────────────────────────────────────────────────────────────────────┘

缓存架构 ​

text
请求级缓存(static::$localCache)    ← 同一请求内不重复查库
        │ 未命中
        ▼
持久缓存(cache() 门面,1小时)      ← 跨请求复用(file/redis)
        │ 未命中
        ▼
数据库查询(dict → dict_item)       ← 查询后写入两级缓存

缓存 Key 格式 ​

缓存类型Key 格式存储内容
请求级$localCache['gender']['1'=>'男', '2'=>'女']
请求级(完整)$localCache['full_gender'][{id, name, value, sort, note}, ...]
持久缓存dict_gender['1'=>'男', '2'=>'女']
持久缓存(完整)dict_full_gender[{id, name, value, sort, note}, ...]

缓存生命周期 ​

text
1. 首次查询 → 数据库 → 写入持久缓存 + 请求级缓存
2. 同一请求再次命中 → 直接返回请求级缓存(最快)
3. 不同请求命中 → 读取持久缓存(不查库)
4. 缓存过期(1小时)→ 重新查库 → 更新两级缓存
5. 字典数据变更 → 调用 clearCache() 清除 → 下次查询重新加载

核心方法 ​

getText — 根据值获取名称(最常用) ​

php
DictService::getText('gender', 1);        // '男'
DictService::getText('user_status', 1);   // '启用'
DictService::getText('gender', '');       // ''(空值返回空字符串)
DictService::getText('gender', null);     // ''(空值返回空字符串)

用途: 列表展示时将数据库值转换为可读名称。

getValue — 根据名称反向获取值 ​

php
DictService::getValue('gender', '男');    // '1'
DictService::getValue('user_status', '启用'); // '1'
DictService::getValue('gender', '');     // ''(空值返回空字符串)

用途: Excel 导入时将中文文字转换为数据库存储的数值。

getOptions — 获取下拉框选项 ​

php
DictService::getOptions('gender');
// [
//     ['label' => '男', 'value' => '1'],
//     ['label' => '女', 'value' => '2'],
// ]

用途: 前端下拉框、单选框、复选框组件的数据源。

getFullItems — 获取完整字典项 ​

php
DictService::getFullItems('gender');
// [
//     ['id' => 1, 'name' => '男', 'value' => '1', 'sort' => 1, 'note' => ''],
//     ['id' => 2, 'name' => '女', 'value' => '2', 'sort' => 2, 'note' => ''],
// ]

用途: 需要 id、排序、备注等完整信息的场景。

clearCache — 清除缓存 ​

php
DictService::clearCache('gender');    // 清除指定字典的缓存
DictService::clearCache();            // 仅清空请求级缓存
DictService::clearAllCache();         // 清除所有字典持久缓存

方法清单 ​

方法说明返回值
getText($code, $value)值 → 名称string
getValue($code, $text)名称 → 值string
getItems($code)获取值→名称映射array ['1'=>'男', '2'=>'女']
getOptions($code)获取下拉框选项array [['label'=>'男','value'=>'1'], ...]
getFullItems($code)获取完整字典项array [{id, name, value, sort, note}, ...]
clearCache($code?)清除指定/请求级缓存void
clearAllCache()清除所有字典缓存void

在 Logic 中使用 ​

自动翻译(serializeMaps) ​

配置 serializeMaps 后,查询数据时自动补全 {字段名}Text 字段,无需手动调用 DictService:

php
class UserLogic extends BaseTenantLogic
{
    /**
     * 枚举显示名映射
     *
     * @var array
     */
    protected array $serializeMaps = [
        'gender' => 'gender',
        'status' => 'user_status',
    ];
}

效果:

text
数据库:{ gender: 1, status: 1 }
    │
    ▼ processSerializeMaps()
    │ DictService::getText('gender', 1) → '男'
    │ DictService::getText('user_status', 1) → '启用'
    ▼
前端接收:{ gender: 1, genderText: '男', status: 1, statusText: '启用' }

手动调用 ​

php
// 在 Logic 或 Service 中手动调用
$genderText = DictService::getText('gender', $user['gender']);
$options = DictService::getOptions('gender');

在 Controller 中使用 ​

获取下拉框数据 ​

php
// app/controller/DictController.php

/**
 * 获取字典项下拉列表
 *
 * GET /dict/getOptions/{code}
 */
public function getOptions(string $code): Json
{
    $options = DictService::getOptions($code);
    return $this->success($options);
}

刷新字典缓存 ​

php
/**
 * 刷新字典缓存
 *
 * GET /dict/refreshCache
 */
public function refreshCache(): Json
{
    DictService::clearAllCache();
    return $this->success(null, '缓存刷新成功');
}

在导入导出中使用 ​

导入时:文字转值 ​

php
// UserLogic::import()
foreach ($data as &$row) {
    // Excel 中"男" → 数据库中 1
    if (!empty($row['gender']) && !is_numeric($row['gender'])) {
        $row['gender'] = DictService::getValue('gender', $row['gender']);
    }
    // Excel 中"启用" → 数据库中 1
    if (!empty($row['status']) && !is_numeric($row['status'])) {
        $row['status'] = DictService::getValue('user_status', $row['status']);
    }
}

导出时:值转文字 ​

php
// 导出表头使用 Text 后缀字段
$headers = [
    'name'       => '姓名',
    'genderText' => '性别',      // 自动翻译后的字段
    'statusText' => '状态',      // 自动翻译后的字段
];

前端集成 ​

获取字典选项 ​

typescript
// API
export function getDictOptions(code: string) {
  return http.request({ url: `/dict/getOptions/${code}`, method: 'GET' });
}

// 使用
const genderOptions = ref([]);
onMounted(async () => {
  genderOptions.value = await getDictOptions('gender');
});

下拉框组件 ​

vue
<template>
  <el-select v-model="form.gender" placeholder="请选择性别">
    <el-option
      v-for="item in genderOptions"
      :key="item.value"
      :label="item.label"
      :value="item.value"
    />
  </el-select>
</template>

数据库表结构 ​

think_dict(字典主表) ​

字段类型说明示例
idINT主键1
nameVARCHAR(50)字典名称性别
codeVARCHAR(50)字典编码(唯一)gender
remarkVARCHAR(500)备注性别字典
...公共字段

think_dict_item(字典项表) ​

字段类型说明示例
idINT主键1
dict_idINT字典 ID(外键)1
nameVARCHAR(50)项名称男
valueVARCHAR(50)项值1
sortINT排序1
noteVARCHAR(200)备注
...公共字段

字典编码规范 ​

字典编码名称项值用途
gender性别0=女, 1=男用户性别
user_status用户状态0=禁用, 1=启用用户账号状态
article_status文章状态0=草稿, 1=已发布文章状态
tenant_status租户状态0=禁用, 1=启用租户状态
example_type案例类型0=类型一, 1=类型二案例分类
example_status案例状态0=禁用, 1=启用案例状态

缓存管理 ​

缓存失效时机 ​

时机操作说明
字典项新增/修改/删除DictService::clearCache($code)清除该字典的缓存
手动刷新GET /dict/refreshCache清除所有字典缓存
缓存过期自动失效1 小时 TTL

字典数据变更后必须刷新缓存

修改字典项后,如果不刷新缓存,前端显示的可能仍是旧数据。建议在字典管理的增删改接口中自动调用 clearCache()。

安全特性 ​

特性说明
两级缓存请求级 + 持久缓存,减少数据库压力
空值安全getText/getValue 对 null/空字符串返回空字符串
类型安全值统一转为字符串比较,避免类型松散比较问题
缓存隔离每个字典编码独立缓存,互不影响

小蚂蚁云团队 · 提供技术支持