Model validations in a lifecycle hook like beforeUpdate

System Information
  • Strapi Version: 4.2.3
  • Operating System: Mac OS 12.4
  • Database: PG 14
  • Node Version: 16.15.0
  • NPM Version:
  • Yarn Version: 1.22.17

Hello there,

I wonder if the community can help me think through an issue I am having with validations. Any help would be much appreciated!

The short version is that I have a field being populated in a beforeUpdate lifecycle hook, where the value is derived from other values. I would like to validate the uniqueness of this field before the change is persisted to the database. It seems that simply adding "unique": true to the schema.json isn’t enough!

The longer version:

I am using as the CMS for a portfolio website. Let’s say I have a collection type called “Books”. Each book has a title, and I want to use that title to create a slug field automatically. I have a beforeCreate and beforeUpdate that populate this field. A front-end framework uses the slug to generate a route. Therefore, I want each slug to be unique. Titles, on the other hand, do not need to be unique — many books can have the same title. It appears that the Entity Validator does not run before update — but rather it runs when the user manually submits data. Is that correct?

Here is a simple reproduction: https://github.com/tylerpaige/strapi-lifecycle-hook-validations

Is there a way I can validate the slug in this situation? Maybe I can call strapi.entityValidator.validateEntityUpdate myself or something?

Even if I could do that, I’m not sure how I would return a useful error message. If I throw an Error, Strapi doesn’t seem to display the message…

Many thanks for any help you all can offer!
-Tyler

1 Like

I have a similar situation where I want to validate the object myself before performing some other task.

I think I got how to manually check for validations in v4 using this way:

const { createCoreService } = require('@strapi/strapi').factories;

module.exports = createCoreService('api::something.something', ({ strapi }) => ({
    async create(params) {
        try {
            const model = strapi.contentTypes[("api::something.something")];

            // const isDraft = isDraft(params.data, model); 
            // dont know how to check for draft, 
            // but it will set to default if 3rd parameter is 
            // not provided in below method call

            const validData = await strapi.entityValidator.validateEntityCreation(model, params.data, {});

            // if validation fails, it will throw an exception which you can handle below

            const result = await super.create(params);

        catch (e) {
            // do something with validation
            throw e;
        }

        return result;
    }
}));

1 Like