如何在Strapi生命周期方法中获取关联字段
问题描述
我的Inventory模型与supplier、product均为一对多关联,现在想在Strapi的afterCreate或afterUpdate生命周期方法生成的event对象中获取这两个关联的完整信息,但目前只能拿到如下结构:
result: { id: 1, availableStockQuantity: 4, uom: 'Kg', createdAt: '2024-07-03T04:54:00.941Z', updatedAt: '2024-07-03T04:54:16.211Z', publishedAt: null, locale: 'en', stockAvailabilityDate: '2024-07-10T04:00:00.000Z', product: { count: 1 }, supplier: { count: 1 }, {...} }
我的Inventory模型生命周期代码:
import { errors } from '@strapi/utils'; import { MessageType, Topic, handleEvent } from '../../../../../config/topics'; const { ApplicationError } = errors; const validateDate = (dateStrUTC: string): void => { const date = new Date(dateStrUTC); const isThursdayMidnight = date.getUTCDay() === 4 && date.getUTCHours() === 0 && date.getUTCMinutes() === 0 && date.getUTCSeconds() === 0 && date.getUTCMilliseconds() === 0; if (!isThursdayMidnight) { throw new ApplicationError('Stock availability can only be set to Thursdays midnight'); } }; interface Inventory { product: string, stockAvailabilityDate: string, supplier: string, availableStockQuantity: number, uom: "Kg" | "Unit" } const cast = (result): Inventory => { return { product: result.name, stockAvailabilityDate: result.stockAvailabilityDate, supplier: "", availableStockQuantity: result.availableStockQuantity, uom: result.uom } } export default { beforeCreate(event) { const { data } = event.params; // validateDate(data.stockAvailabilityDate); }, afterCreate(event) { handleEvent(event, MessageType.Create, cast, Topic.Inventory); }, afterUpdate(event) { console.log("Got this as event", event); handleEvent(event, MessageType.Update, cast, Topic.Inventory); }, };
handleEvent方法代码:
export const handleEvent = <T>(event: any, messageType: MessageType, cast: Caster<T>, topic: Topic) => { const { result } = event; const data = cast(result); const message = buildMessage(data, messageType); sendMessageToQueue(topic, message); };
解决方案
Strapi默认在生命周期的event.result里不会自动填充关联数据,只会返回关联的count值,要获取完整关联信息,有两种常用实现方式:
方式一:手动查询关联数据(通用所有生命周期)
利用Strapi内置查询API,通过当前Inventory的ID查询包含关联字段的完整数据:
修改afterCreate和afterUpdate方法:
export default { // ...保留其他生命周期方法 async afterCreate(event) { // 查询包含关联的完整Inventory数据 const fullInventory = await strapi.db.query('api::inventory.inventory').findOne({ where: { id: event.result.id }, populate: ['product', 'supplier'], // 指定要填充的关联字段名 }); // 将完整数据传入handleEvent handleEvent({ ...event, result: fullInventory }, MessageType.Create, cast, Topic.Inventory); }, async afterUpdate(event) { const fullInventory = await strapi.db.query('api::inventory.inventory').findOne({ where: { id: event.result.id }, populate: ['product', 'supplier'], }); handleEvent({ ...event, result: fullInventory }, MessageType.Update, cast, Topic.Inventory); }, };
同步修改cast函数,从完整数据中提取关联字段信息:
const cast = (result): Inventory => { return { product: result.product.name, // 假设product模型包含name字段 stockAvailabilityDate: result.stockAvailabilityDate, supplier: result.supplier.name, // 假设supplier模型包含name字段 availableStockQuantity: result.availableStockQuantity, uom: result.uom } }
方式二:设置查询populate选项(仅适用于afterUpdate)
在beforeUpdate中添加populate参数,让Strapi更新后直接返回填充了关联的数据:
export default { beforeUpdate(event) { // 配置要填充的关联字段 event.params.populate = ['product', 'supplier']; }, async afterUpdate(event) { // 此时event.result已包含完整的product和supplier数据 handleEvent(event, MessageType.Update, cast, Topic.Inventory); }, };
注意:该方式对afterCreate不生效,因为beforeCreate无法通过设置populate影响创建后的返回结果。
注意事项
- populate字段必须与模型中定义的关联字段名完全一致。
- 若只需关联数据的特定字段,可通过嵌套配置精简返回内容,例如:
populate: { product: { select: ['id', 'name'] } }。
内容的提问来源于stack exchange,提问作者user9132502
相关产品推荐
相关产品推荐

