我目前正在使用 Sanity.io 作为我的内容管理系统来构建一个博客网站。在此过程中,我为帖子和作者创建了模式。我的目标是确保 post slugs 是唯一的,这导致我实施了验证规则。但是,我面临一个令人费解的问题,当我导航到 localhost:3333 创建新帖子时,我收到的不是一条,而是两条错误消息,这些错误消息针对与 slug 字段的唯一性相关的相同验证规则。
另一方面,作者电子邮件字段的唯一性验证运行正常。以下是我的开发环境的具体情况:
我投入了大量时间试图解决这个问题,但没有成功。我正在寻求帮助来理解为什么 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,
},
}),
],
});
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;
}),
],
}),
],
});
我非常感谢任何解决此问题的指导或帮助。如果您需要其他代码片段或更多详细信息来提供帮助,请随时告诉我。
感谢您的支持!
我正在探索有关“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,
},
}),
],
});
通过实现此代码,您可以自定义自定义验证逻辑生成的错误消息。这对于向用户提供更多信息丰富且用户友好的错误消息非常有价值。
有关更多信息,您可以参阅 Sanity Slug Field 文档此处了解更多详细信息。
这种方法使您能够有效地管理错误消息并强制执行 slug 的唯一性,同时保留根据您的特定需求进行定制的灵活性。”