目录

Strapi Slug 系统的建立

目录

Strapi Slug 系统的建立

在前一篇文章的基础上进行,即Docker上的Strapi如何建立Slug系统,本文给出了修改步骤。

本文针对中文标题的生成,用到两个库:pinyinslugify

  1. 手动添加依赖到 package.js
  2. 删除 node_modulespackage-lock.js
  3. 修改并保存对应 apimodel 中的文件
  4. 重新运行容器 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 中只能获取 typeidcategorytype 字段保存的是对应typeid

在使用 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: