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钩子在 INSERTUPDATE 查询之前被调用。
  • 钩子可以是异步的。因此,你可以在其中使用await关键字。
  • 钩子总是被定义为静态函数,并接收模型的实例作为第一个参数。

了解$dirty属性

每次使用模型实例 createdupdated 新用户时,都会调用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 方法同时触发 beforeFetchbeforePaginate 钩子。

钩子函数接收一组查询构建器。第一个实例用于计数查询,第二个实例用于主查询。

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 方法会触发 afterFetchafterPaginate 钩子。

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>) {
  }
}

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/adonisjs/5.x/mo...

译文地址:https://learnku.com/docs/adonisjs/5.x/mo...

上一篇 下一篇
贡献者:2
讨论数量: 0
发起讨论 只看当前版本


暂无话题~