SvelteKit/Prisma中URL去撇号后的数据库查询问题
解决方案:解决URL参数与数据库名称匹配的字符问题
核心问题
你当前的方案通过将带撇号的名称转成短横线形式的URL(如User's Spellbook→users-spellbook),但反向转换后丢失了撇号,导致无法匹配数据库中的原名称。contains未生效大概率是因为MySQL默认区分大小写,且转换后的字符串与原名称差异(缺失撇号)导致匹配失败。
推荐以下两种可靠方案:
方案1:使用Spellbook的ID作为URL参数(最简洁可靠)
直接用数据库中Spellbook的唯一ID代替名称作为URL参数,彻底规避字符编码问题:
- 修改路由路径为
/spellbooks/[spellbookId] - 更新
+page.server.ts代码:
import { prisma } from '$lib/server/prisma'; import type { RequestHandler } from '@sveltejs/kit'; export const GET: RequestHandler = async ({ params }) => { const spellbookId = parseInt(params.spellbookId); if (isNaN(spellbookId)) { return new Response(JSON.stringify({ message: '无效的咒语本ID' }), { status: 400 }); } const spellbook = await prisma.spellbook.findUnique({ where: { id: spellbookId }, include: { spells: { include: { classes: true, components: true, description_list: true } } } }); if (!spellbook) { return new Response(JSON.stringify({ message: '未找到对应咒语本' }), { status: 404 }); } return new Response(JSON.stringify(spellbook), { status: 200 }); };
方案2:新增Slug字段专门用于URL(保留名称语义)
在数据库中存储一个专门用于URL的标准化slug字段,创建咒语本时生成对应的slug,查询时直接匹配:
- 更新
schema.prisma的Spellbook模型,新增slug字段:
model Spellbook { id Int @id @default(autoincrement()) user_id String spellbook_name String @unique slug String @unique // 新增:用于URL的标准化名称 character_name String spellbook_description String? @db.VarChar(1000) class Class image_url String created_at DateTime @default(now()) updated_at DateTime @updatedAt auth_user AuthUser @relation(fields: [user_id], references: [id]) spells Spell[] @relation("SpellToSpellbook") @@index([user_id]) @@map("spellbook") }
执行prisma migrate dev更新数据库结构。
- 编写slug生成函数,在创建咒语本时生成对应的slug:
function generateSlug(name: string): string { return name .toLowerCase() .replace(/['’]/g, '') // 移除撇号 .replace(/\s+/g, '-') // 空格替换为短横线 .replace(/[^a-z0-9-]/g, ''); // 移除其他特殊字符 } // 创建咒语本时调用 await prisma.spellbook.create({ data: { spellbook_name: "User's Spellbook", slug: generateSlug("User's Spellbook"), // 生成users-spellbook user_id: "xxx", character_name: "xxx", class: "Wizard", image_url: "xxx" } });
- 修改
+page.server.ts直接匹配slug:
import { prisma } from '$lib/server/prisma'; import type { RequestHandler } from '@sveltejs/kit'; export const GET: RequestHandler = async ({ params }) => { const slug = params.spellbookName; const spellbook = await prisma.spellbook.findFirst({ where: { slug }, include: { spells: { include: { classes: true, components: true, description_list: true } } } }); if (!spellbook) { return new Response(JSON.stringify({ message: '未找到对应咒语本' }), { status: 404 }); } return new Response(JSON.stringify(spellbook), { status: 200 }); };
临时应急方案(不推荐)
如果暂时无法修改数据库,可尝试不区分大小写的模糊匹配,但存在重名匹配错误的风险:
const spellbookName = params.spellbookName?.replace(/-/g, ' '); const spellbook = await prisma.spellbook.findFirst({ where: { spellbook_name: { contains: spellbookName, mode: 'insensitive' // 忽略大小写 } }, include: { spells: { include: { classes: true, components: true, description_list: true } } } });
内容的提问来源于stack exchange,提问作者ezzy-dev
相关产品推荐
相关产品推荐

