理智中的验证问题:Slug 唯一性检查的重复错误

问题描述 投票:0回答:1

我目前正在使用 Sanity.io 作为我的内容管理系统来构建一个博客网站。在此过程中,我为帖子和作者创建了模式。我的目标是确保 post slugs 是唯一的,这导致我实施了验证规则。但是,我面临一个令人费解的问题,当我导航到 localhost:3333 创建新帖子时,我收到的不是一条,而是两条错误消息,这些错误消息针对与 slug 字段的唯一性相关的相同验证规则。

另一方面,作者电子邮件字段的唯一性验证运行正常。以下是我的开发环境的具体情况:

  • 操作系统:Windows 10
  • Node.js 版本:18.15.0
  • 理智版本:3.18.1
  • TypeScript 用于我的项目。

我投入了大量时间试图解决这个问题,但没有成功。我正在寻求帮助来理解为什么 slug 字段会为相同的验证生成两条错误消息。

post.ts 代码:

import { defineField, defineType, SlugRule } from "sanity";

export default defineType({
    name: "post",
    title: "Post",
    type: "document",
    fields: [
        defineField({
            name: "title",
            title: "Post Title",
            type: "string",
            validation: (Rule) => [Rule.required().error("This field should not be left blank.")],
        }),
        defineField({
            name: "slug",
            title: "Post Slug",
            type: "slug",
            validation: (Rule: SlugRule) => [
                Rule.required().error("This field should not be left blank."),
                Rule.custom(async (value, context) => {
                    if (!value?.current) return true; // Skip custom validation if the field is empty
                    const { document, getClient } = context;
                    const client = getClient({ apiVersion: "v2022-12-07" });

                    // Check another post already taken this slug.
                    const params = { slug: value?.current, id: document?._id };
                    const query = "*[_type == 'post' && slug.current == $slug && _id != $id]";
                    const posts = await client.fetch(query, params);

                    if (posts.length > 0) return "This slug is already taken.";
                    return true;
                }),
            ],
            options: {
                source: "title",
                maxLength: 96,
            },
        }),
    ],
});

错误截图: Post Page

author.ts代码:

import { StringRule, defineField, defineType } from "sanity";

export default defineType({
    name: "author",
    title: "Author",
    type: "document",
    fields: [
        defineField({
            name: "name",
            title: "Name",
            type: "string",
            validation: (Rule) => [Rule.required().error("This field should not be left blank.")],
        }),
        defineField({
            name: "email",
            title: "Email Address",
            type: "string",
            validation: (Rule: StringRule) => [
                Rule.required().error("This field should not be left blank."),
                Rule.email().error("Please enter a valid email address."),
                Rule.custom(async (value, context) => {
                    if (!value) return true; // Skip custom validation if the field is empty
                    const { document, getClient } = context;
                    const client = getClient({ apiVersion: "2022-12-07" });

                    // Check another author already taken this email address.
                    const params = { email: value, id: document?._id };
                    const query = "*[_type == 'author' && email == $email && _id != $id]";
                    const authors = await client.fetch(query, params);

                    if (authors.length > 0) return "This email address is already taken.";
                    return true;
                }),
            ],
        }),
    ],
});

错误截图: Author Page

我非常感谢任何解决此问题的指导或帮助。如果您需要其他代码片段或更多详细信息来提供帮助,请随时告诉我。

感谢您的支持!

validation schema sanity
1个回答
0
投票

我正在探索有关“slug”字段的 Sanity 文档,值得注意的是,默认情况下,“slug”字段本质上并不是唯一的。相反,确保 slug 的唯一性通常需要使用自定义验证逻辑。因此,在使用 slug 验证时,您可能会遇到两条错误消息:一条来自 Sanity 的默认行为,另一条来自您的自定义验证逻辑。

要解决这种情况并自定义错误消息,您可以使用以下代码片段:

import { defineField, defineType, SlugRule } from "sanity";

export default defineType({
    name: "post",
    title: "Post",
    type: "document",
    fields: [
        defineField({
            name: "title",
            title: "Post Title",
            type: "string",
            validation: (Rule) => [Rule.required().error("This field should not be left blank.")],
        }),
        defineField({
            name: "slug",
            title: "Post Slug",
            type: "slug",
            validation: (Rule: SlugRule) => [
                Rule.required().error("This field should not be left blank."),
                Rule.custom(async (value, context) => {
                    if (!value?.current) return true; // Skip custom validation if the field is empty
                    const { document, getClient } = context;
                    const client = getClient({ apiVersion: "2023-10-23" });

                    // Note: Query finds a published post by slug, excluding drafts, and retrieves its ID.
                    const params = { slug: value?.current, id: document?._id.replace(/^drafts\./, "") };
                    const query = "*[_type == 'post' && slug.current == $slug && !(_id in path('drafts.**')) && _id != $id] { _id }";
                    const posts = await client.fetch(query, params);

                    if (posts.length > 0) return "This slug is already taken.";
                    return true;
                }),
            ],
            options: {
                source: "title",
                maxLength: 96,
                isUnique: () => true,
            },
        }),
    ],
});

通过实现此代码,您可以自定义自定义验证逻辑生成的错误消息。这对于向用户提供更多信息丰富且用户友好的错误消息非常有价值。

作为参考,下面是输出的示例图像: Post Page

有关更多信息,您可以参阅 Sanity Slug Field 文档此处了解更多详细信息。

这种方法使您能够有效地管理错误消息并强制执行 slug 的唯一性,同时保留根据您的特定需求进行定制的灵活性。”

© www.soinside.com 2019 - 2024. All rights reserved.