カスタムモデル
アプリケーションが成長するにつれて、関連するロジックをグループ化する必要がある場合があります。次のいずれかの方法をお勧めします。
- 静的メソッドの作成にはPrisma Client拡張を使用する
- モデルをクラスにラップする
- Prisma Clientモデルオブジェクトの拡張
Prisma Client拡張機能による静的メソッド
次の例では、`signUp` および `findManyByDomain` メソッドをUserモデルに追加するPrisma Client拡張を作成する方法を示します。
- Prisma Client拡張
- Prismaスキーマ
import bcrypt from 'bcryptjs'
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient().$extends({
model: {
user: {
async signUp(email: string, password: string) {
const hash = await bcrypt.hash(password, 10)
return prisma.user.create({
data: {
email,
password: {
create: {
hash,
},
},
},
})
},
async findManyByDomain(domain: string) {
return prisma.user.findMany({
where: { email: { endsWith: `@${domain}` } },
})
},
},
},
})
async function main() {
// Example usage
await prisma.user.signUp('user2@example2.com', 's3cret')
await prisma.user.findManyByDomain('example2.com')
}
"prisma/schema.prisma"
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
id String @id @default(cuid())
email String
password Password?
}
model Password {
hash String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String @unique
}
モデルをクラスにラップする
以下の例では、Prisma Clientの `user` モデルを `Users` クラス内にラップする方法を示します。
import { PrismaClient, User } from '@prisma/client'
type Signup = {
email: string
firstName: string
lastName: string
}
class Users {
constructor(private readonly prismaUser: PrismaClient['user']) {}
// Signup a new user
async signup(data: Signup): Promise<User> {
// do some custom validation...
return this.prismaUser.create({ data })
}
}
async function main() {
const prisma = new PrismaClient()
const users = new Users(prisma.user)
const user = await users.signup({
email: 'alice@prisma.io',
firstName: 'Alice',
lastName: 'Prisma',
})
}
この新しい `Users` クラスを使用すると、`signup` のようなカスタム関数を定義できます。
上記の例では、Prisma Clientから `signup` メソッドのみを公開していることに注意してください。Prisma Clientは `Users` クラス内に隠されているため、`findMany` や `upsert` のようなメソッドを呼び出すことはできなくなります。
このアプローチは、大規模なアプリケーションがあり、モデルができることを意図的に制限したい場合にうまく機能します。
Prisma Clientモデルオブジェクトの拡張
しかし、既存の機能を隠したくないが、カスタム関数をグループ化したい場合はどうでしょうか?この場合、`Object.assign` を使用して、Prisma Clientの機能を制限することなく拡張できます。
import { PrismaClient, User } from '@prisma/client'
type Signup = {
email: string
firstName: string
lastName: string
}
function Users(prismaUser: PrismaClient['user']) {
return Object.assign(prismaUser, {
/**
* Signup the first user and create a new team of one. Return the User with
* a full name and without a password
*/
async signup(data: Signup): Promise<User> {
return prismaUser.create({ data })
},
})
}
async function main() {
const prisma = new PrismaClient()
const users = Users(prisma.user)
const user = await users.signup({
email: 'alice@prisma.io',
firstName: 'Alice',
lastName: 'Prisma',
})
const numUsers = await users.count()
console.log(user, numUsers)
}
これで、カスタムの `signup` メソッドを `count`、`updateMany`、`groupBy()`、その他Prisma Clientが提供するすべての素晴らしいメソッドとともに使用できます。何よりも、すべて型安全です!
さらに詳しく
Prisma Client拡張機能を使用して、カスタムモデルメソッドでモデルを拡張することを推奨します。