如何使用 find 或 findOrFail 自动加载与 Adonis 的关系?

How to autoload a relationship with Adonis with find or findOrFail?

有没有办法自动加载与 findByOrFail 的关系(或任何其他方法,如 find 等)?

在下面的代码中,未定义方法 with()

async show({ params, response }) {
  try {
    return await Company.findByOrFail('domain', params.id).with('websites')
  } catch (error) {
    console.error(error)

    switch (error.name) {
      case 'ModelNotFoundException':
        return response.notFound({ message: 'companies_show_not_found' })

      default:
        return response.badRequest({ message: 'something_went_wrong' })
    }
  }
}

看起来最干净的解决方案是使用 globalScope

class Company extends Model {
  static boot() {
    super.boot()

    this.addGlobalScope(function (builder) {
      builder.with('websites')
    })
  }

  websites() {
    return this.hasMany('App/Models/Website')
  }
}

为什么不直接用这样的查询来做:

await Company.query().where('domain', params.id).with('websites').firstOrFail()

你可以像这样使用关系

async show({ params, response }) {
  try {
    const relationdata= await Company.findByOrFail('domain', params.id)
return await relationdata.websites().fetch()
  } catch (error) {
    console.error(error)

    switch (error.name) {
      case 'ModelNotFoundException':
        return response.notFound({ message: 'companies_show_not_found' })

      default:
        return response.badRequest({ message: 'something_went_wrong' })
    }
  }
}

Adonis 5 在预定义的生命周期事件期间支持 hooks 运行。

所以理想情况下你可以做这样的事情。

class Company extends Model {
  
  @hasMany()
  public static websites: HasMany<typeof Website>

  @beforeFetch() 
  @beforeFind() 
  public static fetchWebsites(query: ModelQueryBuilderContract<typeof Company>) { 
    query.preload('websites')
  }
}

然后当您获取公司时,结果将包含关系。

Company.all()
{
  'name': 'company_name', 
  'websites': [
   {
     'name': 'my site', 
     'url': 'my.site'
   }
   ...
  ]
}