当前位置: 首页
AI教程
PHP程序员转型AI与Golang:管理员角色组关联

PHP程序员转型AI与Golang:管理员角色组关联

热心网友 时间:2026-08-05
转载

基于AI工具从PHP转向Golang开发,完成管理员与角色组关联功能。通过GORM预加载复习,优化关联配置与仓储层调用,实现关联表字段筛选,并支持子查询完成跨表条件过滤,提升数据查询效率。

这是一个系列文章,我将以PHP全栈工程师的身份,借助AI工具(TRAE、claude code、codex、deepseek、豆包等),从零开始学习Golang语言,并最终完成ai-go-admin开源项目的制作。全程记录,分享经验。

从 PHP 到 AI + Golang,程序员自救转型手记(五十一):管理员和角色组的关联

上一期我们完成了“增加管理员角色组管理”,这一期接着做:管理员和角色组的关联。

管理员和角色组的关联

系统里目前还没用上关联表,这次就拿管理员角色组来跑通整个流程。先让AI给个方案,切换到plan模式:接下来需要完成AdminAdminGroupAccess模型的关联,它们定义在@internal/model/admin.go,用什么方式关联比较好?同时,我需要为基类增加快速配置关联的功能,在什么地方配置,配置名叫什么比较好?

GORM 预加载复习

上面那段提示词说得比较笼统,连关联模式都让AI自己选。在它分析的时候,我赶紧翻出GORM的学习笔记,重新过一遍各种关联方式的预加载写法。

预加载的写法有:

Preload

type User struct {
    gorm.Model
    Username string
    Orders []Order
}

type Order struct {
    gorm.Model
    UserID uint
    Price float64
}

// 预加载 Order 数据,参数二可以传递一个 func(db gorm.PreloadBuilder) error 闭包函数,里边拼接查询条件、排序方式等
.Preload("Order", nil)

// 条件预加载
.Preload("Orders", "state NOT IN (?)", "cancelled")

// 嵌套
.Preload("Orders.OrderItems.Product")

Joins 预加载

还是上面的模型定义,用 Joins 预加载是这样写的:

// 参数二同样可以传递一个闭包,签名是: func(db gorm.JoinBuilder, joinTable clause.Table, curTable clause.Table) error
.Joins(clause.JoinTarget{Association: "Order"}, nil)

Joins 预加载性能最好,因为它在单条 SQL 里用左连接加载关联数据。

AI 初版完成

AI 给的方案一般般,刚复习完笔记再看,甚至有点low。首先是在控制器里加了个可选参数函数WithPreloads,然后把设置的Preloads传到仓储层,仓储层直接:

// 预加载关联
for _, p := range opts.Preloads {
    q = q.Preload(p, func(pb gorm.PreloadBuilder) error { return nil })
}

用的是Preload写法,加载是加载了,但闭包函数固定返回nil。下面逐一列出问题和改进点。

参数和 GORM 的 Preloads 同步

// Preload 预加载关联配置
type Preload struct {
    Name  string                                                       // 关联名称
    Query func(gorm.PreloadBuilder) error // 可选的自定义查询条件,为 nil 时仅按名称预加载
}

AI 上来就定义了一个type Preload struct,第一个字段是Name string。我对比了一下Preload的签名,它第一个参数是association string,这个 AI 不严谨,先让它改过来。

控制器层关联配置优化

// PreloadFields 声明对应方法的预加载关联配置
type PreloadFields struct {
    Get    []repository.Preload
    List   []repository.Preload
    Update []repository.Preload
    Create []repository.Preload
}

这是 AI 模仿ActionFields搞出来的,给Get、List、Update、Create各配了一个Preload位置。但Update、Create里这些东西基本没用,直接去掉。List是主要使用方,Get用得少,就算额外查了ListPreload也没关系。所以简化成单个Preloads []repository.Preload配置就行,不需要区分方法。

仓储层 Preload 调用优化

AI 原本这样写:

for _, p := range opts.Preloads {
    query := p.Query
    if query == nil {
        query = func(pb gorm.PreloadBuilder) error { return nil }
    }
    q = q.Preload(p.Association, query)
}

实际上直接写q = q.Preload(p.Association, nil)就行,不需要nil守卫,直接去掉。

关联筛选查询

我们的表格支持多字段筛选,比如用关联模型groupname字段模糊查询。前端几乎不用改,表格组件和表格管家的公共搜索组件自然能传递这种数据到服务端:

{
    wheres: [
        { field: 'group.name', operator: 'ILIKE', value: '1' },
        { field: 'group.title', operator: 'ILIKE', value: '1' }
    ],
    or: true
}

问题在于服务端在哪里应用这些筛选数据。首先想到的是用Preload(association string, query func(db gorm.PreloadBuilder)的第二个闭包函数,但这个理解是错的:

gorm.G[Admin](db).Preload("Group", func(pb PreloadBuilder) error {
    pb.Where("name LIKE ?", "%foo%")
    return nil
}).Find(ctx)

会产生两条 SQL:

-- 1. 主查询:所有 Admin,全部返回
SELECT * FROM admins;

-- 2. 预加载:只加载 name LIKE 'foo' 的 group
SELECT * FROM admin_groups WHERE id IN (?, ?, ?) AND name LIKE '%foo%';

结果就是所有Admin都会出现在结果里,只是部分行(不匹配的)的Group数据被置为nil

我们想要的筛选语义是:只返回group.name匹配的Admin行。这需要主查询过滤,Preload帮不上忙。唯一干净的方式是子查询,顺着关联链层层套EXISTS/IN子查询就行。

SELECT * FROM admins WHERE admins.group_id IN (
    SELECT id FROM admin_groups WHERE name LIKE '%foo%'
);

就按子查询的方式让AI实现出来,在已有的BuildWhereScopes、BuildWhereExpr里完成关联表字段名检查等。实际实现比较复杂,人工review了很久,好在最终做出来了,而且很优雅。现在前端可以直接发任意表的筛选数据,最终组装好对应的SQL进行查询,比如主表的name LIKE '%foo%',关联表的group.name LIKE '%foo%'

来源:https://juejin.cn/post/7669993495222517770

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
WorkBuddy使用一个月避坑指南:5个常见问题及解决方案

WorkBuddy使用一个月避坑指南:5个常见问题及解决方案

使用WorkBuddy一个月,踩过指令模糊、未指定输出格式、反复打断任务、积分过期、未验证结果五个坑。对应解法:明确文件路径、动作、维度、格式和文件名;指定输出格式;耐心等待;优先使用快过期积分;抽查验证汇总逻辑。

时间:2026-08-05 22:59
图片生成任务到用户隔离:AIGC后端与PostgreSQL建模实践

图片生成任务到用户隔离:AIGC后端与PostgreSQL建模实践

基于AIGCCreativeStudio实践,后端采用Express+TypeScript与PostgreSQL17,通过users、generation_tasks、images三表模型实现任务状态机、图片本地存储及受认证访问,确保用户隔离与资源安全。

时间:2026-08-05 22:59
动态代码拖累SEO?用Gofair纯静态页面剔除冗余代码

动态代码拖累SEO?用Gofair纯静态页面剔除冗余代码

静态页面加载速度快,搜索引擎爬取效率高,优于动态建站。某孕产妇用品企业改用Gofair静态建站,五天多关键词冲至谷歌首页。SEO效果需通过关键词反查验证,流量数据易被干扰。未来静态页面策略将更主流。

时间:2026-08-05 22:59
WorkBuddy AI工作台实操教程 零基础搞定周报与数据分析

WorkBuddy AI工作台实操教程 零基础搞定周报与数据分析

使用WorkBuddy时需下达清晰指令,包括文件路径、输出格式和完整需求。典型场景如周报生成、Excel数据清洗与可视化,需注意指定去重列和输出格式,避免打断大文件处理。定时任务可自动化抓取新闻,轻量模型和Ask模式可节省积分。

时间:2026-08-05 22:58
CC压缩机制之toolResultBudget源码实现原理技术深度解读

CC压缩机制之toolResultBudget源码实现原理技术深度解读

toolResultBudget机制在每次模型请求前自动执行,检查单个API-levelusermessage中tool_result总量是否超过200K字符,若超则将最大的工具结果落盘并替换为预览,以降低上下文噪音。该机制位于压缩流水线最前端,在microcompact之前执行,确保后续压缩更高效。

时间:2026-08-05 22:58
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 热门数据榜