ORM 钩子
挂钩是在预定义的生命周期事件期间你可以对模型实例执行的操作。使用钩子,你可以在模型中封装特定操作,而不是在代码库中的任何地方编写它们。
钩子的一个很好的例子是密码散列。你可以定义一个在save
调用之前运行的挂钩,并将纯文本密码转换为哈希值。
// title: app/Models/User.ts
// 高亮开始
import Hash from '@ioc:Adonis/Core/Hash'
// 高亮结束
import { column, beforeSave, BaseModel } from '@ioc:Adonis/Lucid/Orm'
export default class User extends BaseModel {
@column({ isPrimary: true })
public id: number
@column()
public email: string
@column()
public password: string
// 高亮开始
@beforeSave()
public static async hashPassword (user: User) {
if (user.$dirty.password) {
user.password = await Hash.make(user.password)
}
}
// 高亮结束
}
beforeSave
钩子在 INSERT 和 UPDATE 查询之前被调用。- 钩子可以是异步的。因此,你可以在其中使用
await
关键字。 - 钩子总是被定义为静态函数,并接收模型的实例作为第一个参数。
了解$dirty
属性
每次使用模型实例 created 或 updated 新用户时,都会调用beforeSave
挂钩。
在更新期间,你可能更新了其他属性,但没有更新用户密码。因此不需要重新散列现有的散列,这就是使用$dirty
对象的原因。
$dirty
对象仅包含更改的值。因此,你可以检查密码是否已更改,然后对新值进行哈希处理。
可用的钩子
以下是所有可用钩子的列表。请务必阅读 decorators API 文档。
钩子 | 描述 |
---|---|
beforeSave |
在插入或更新查询之前调用,接收模型实例作为唯一参数 |
afterSave |
在插入或更新查询之后调用。接收模型实例作为唯一参数 |
beforeCreate |
仅在插入查询之前调用,接收模型实例作为唯一参数 |
afterCreate |
仅在插入查询之后调用,接收模型实例作为唯一参数 |
beforeUpdate |
仅在更新查询之前调用,接收模型实例作为唯一参数 |
afterUpdate |
仅在更新查询之后调用,接收模型实例作为唯一参数 |
beforeDelete |
在删除查询之前调用,接收模型实例作为唯一参数 |
afterDelete |
在删除查询之后调用,接收模型实例作为唯一参数 |
beforePaginate |
在分页查询之前调用,接收查询主构建器实例以及计数查询构建器实例 |
afterPaginate |
在分页查询之后调用,接收查询主构建器实例以及计数查询构建器实例 |
beforeFetch |
在 fetch 查询之前调用,接收查询生成器实例作为唯一参数 |
afterFetch |
在 fetch 查询之后调用,接收模型实例数组 |
beforeFind |
在 find 查询之前调用,接收查询生成器实例作为唯一参数 |
afterFind |
在 find 查询之后调用。接收模型实例作为唯一参数 |
所有钩子都接收模型实例作为第一个参数,除了下面的:
beforeFind
beforeFind
钩子在执行查询以查找单行之前被调用,接收查询构建器实例,你可以将对其添加约束。
import {
BaseModel,
beforeFind,
ModelQueryBuilderContract,
} from '@ioc:Adonis/Lucid/Orm'
export default class User extends BaseModel {
@beforeFind()
public static ignoreDeleted (query: ModelQueryBuilderContract<typeof User>) {
query.whereNull('is_deleted')
}
}
afterFind
afterFind
事件接收模型实例。
import {
BaseModel,
afterFind,
} from '@ioc:Adonis/Lucid/Orm'
export default class User extends BaseModel {
@afterFind()
public static afterFindHook (user: User) {
}
}
beforeFetch
与 beforeFind
类似,beforeFetch
钩子也接收查询构建器实例。但是,只要不使用 first
方法执行查询,就会调用此钩子。
import {
BaseModel,
beforeFetch,
ModelQueryBuilderContract,
} from '@ioc:Adonis/Lucid/Orm'
export default class User extends BaseModel {
@beforeFetch()
public static ignoreDeleted (query: ModelQueryBuilderContract<typeof User>) {
query.whereNull('is_deleted')
}
}
afterFetch
afterFetch
钩子接收模型实例数组。
import {
BaseModel,
afterFetch,
} from '@ioc:Adonis/Lucid/Orm'
export default class User extends BaseModel {
@afterFetch()
public static afterFetchHook (users: User[]) {
}
}
beforePaginate
beforePaginate
查询在你使用 paginate
方法时执行。 paginate 方法同时触发 beforeFetch
和 beforePaginate
钩子。
钩子函数接收一组查询构建器。第一个实例用于计数查询,第二个实例用于主查询。
import {
BaseModel,
beforePaginate,
ModelQueryBuilderContract,
} from '@ioc:Adonis/Lucid/Orm'
export default class User extends BaseModel {
@beforePaginate()
public static ignoreDeleted ([
countQuery: ModelQueryBuilderContract<typeof User>,
query: ModelQueryBuilderContract<typeof User>,
]) {
query.whereNull('is_deleted')
countQuery.whereNull('is_deleted')
}
}
afterPaginate
afterPaginate
钩子接收 SimplePaginator 类的实例。paginate
方法会触发 afterFetch
和 afterPaginate
钩子。
import {
BaseModel,
afterPaginate,
} from '@ioc:Adonis/Lucid/Orm'
import {
SimplePaginatorContract
} from '@ioc:Adonis/Lucid/Database'
export default class User extends BaseModel {
@afterPaginate()
public static afterPaginateHook (users: SimplePaginatorContract<User>) {
}
}
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。