Strapi Slug 系统的建立
Strapi Slug 系统的建立
在前一篇文章的基础上进行,即Docker上的Strapi如何建立Slug系统,本文给出了修改步骤。
本文针对中文标题的生成,用到两个库:pinyin 和 slugify。
- 手动添加依赖到 
package.js - 删除     
node_modules、package-lock.js - 修改并保存对应 
api的model中的文件 重新运行容器(程序自动检测文件的修改,会自动重启,不需要手动重启)docker restart my-strapi
别想着通过 docker exec -it my-strapi /bin/bash 或者 docker exec -it my-strapi npm install --save slugify 会出现莫名其妙的错误,总之,删依赖然后重新 npm install 是万能解决方案。
请根据步骤进行,后文给出步骤2和步骤3的具体内容。
    "slugify": "^1.6.5",
    "pinyin": "^2.10.2"
这是本文写作时的最新版本号。
在 api 文件夹的对应位置,本文是strapi/api/post/models/post.js,写下钩子:
const slugify = require('slugify');
const pinyin = require("pinyin");
module.exports = {
  lifecycles: {
    async beforeCreate(data) {
      if (data.title) {
        data.slug = slugify(pinyin(data.title, {
          style: pinyin.STYLE_NORMAL
        }), {
          lower: true
        });
      }
    },
    async beforeUpdate(params, data) {
      if (data.title) {
        data.slug = slugify(pinyin(data.title, {
          style: pinyin.STYLE_NORMAL
        }), {
          lower: true
        });
      }
    }
  }
}
场景:
category 中设置了引用类型,一个 category 对应一个 type,一个 type 有多个 category。
那么 category 创建时的 slug 需要查询 type 获取对应的 code。
原因是 hook 中只能获取 type 的 id即category 的type 字段保存的是对应type的id。
在使用 strapi 暴露的 query.findOne 方法时,不尽人意,因为会获取到不必要的字段,需要投影查询也就是SQL常用的 select。
官方文档 Models | Strapi 中,给出了如何自定义查询的方法,此时需要使用对应的底层 ORM 模型,使用query.model 方法然后使用对应的ORM方法即可,ORM模型提供了 SQL 和 MongoDB 两种,这里我们自然选择 MongoDB。
给出代码:
 const slugify = require('slugify');
 const pinyin = require("pinyin");
 
 module.exports = {
   lifecycles: {
     async beforeCreate(data) {
       if (data.name) {
         let words = pinyin(data.name, {
           style: pinyin.STYLE_NORMAL
         })
         words = [].concat(...words)
         if (data.type) {
           // 使用 strapi query model 来自定义查询; 注意使用对应的 ORM 语法,查询id的时候应该是 _id
           let type = await strapi.query('type').model.findOne({ _id: data.type }, "code").exec();
           if (type) {
            words.unshift(type.code);
           }
         }
         words = words.join(' ');
         data.slug = slugify(words, {
           lower: true
         });
       }
     },
     async beforeUpdate(params, data) {
       if (data.name) {
         let words = pinyin(data.name, {
           style: pinyin.STYLE_NORMAL
         })
         words = [].concat(...words)
         if (data.type) {
           // 使用 strapi query model 来自定义查询; 注意使用对应的 ORM 语法,查询id的时候应该是 _id
           let type = await strapi.query('type').model.findOne({ _id: data.type }, "code").exec();
           if (type) {
            words.unshift(type.code);
           }
         }
         words = words.join(' ');
         data.slug = slugify(words, {
           lower: true
         });
       }
     }
   }
 }
核心语句是:await strapi.query('type').model.findOne({ _id: data.type }, "code").exec(); ,其中的 findOne 方法是 mongoosejs 官方文档中查询到的,包括使用字符串进行投影的"code"。这里要注意的是查询的是底层MongoDB数据库,打开看看,发现其中并没有保存id字段,有的只是_id,这一点需要注意,否则查询结果可能为 null。
Thanks to: