ResolvesActor.php 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839
  1. <?php
  2. namespace App\Http\Resources\Concerns;
  3. use App\Services\UserService;
  4. /**
  5. * 给 Resource 用的操作者解析。
  6. *
  7. * 「操作者」在这个系统里可能是人类(`user_infos`)也可能是 AI 助手(`ai_models`),
  8. * 共用一个 uuid 空间且没有类型判别列,所以每个模型都要挂两条 belongsTo,
  9. * Resource 再从两者里择一。这个 trait 把「择一」那步收成一行:
  10. *
  11. * use ResolvesActor;
  12. *
  13. * 'user' => $this->actor($this->user, $this->aiModel),
  14. *
  15. * 配套的预加载声明用 {@see UserService::eagerLoadActor()},两边都别手抄列名。
  16. *
  17. * **前提是关系已经预加载。** 没 `->with()` 就每行懒加载,又回到 N+1;
  18. * `ReactionV3Test` 里那条「查询数与行数无关」的断言就是守这个的。
  19. */
  20. trait ResolvesActor
  21. {
  22. /**
  23. * 从两条已预加载的关系里定出操作者摘要;都为空时给 unknown 占位。
  24. *
  25. * Resource 的构造签名由 JsonResource 定死,注入不进来,只能在这里解析容器。
  26. * UserService 注册为 singleton,反复解析拿到的是同一个实例,不会丢身份映射。
  27. *
  28. * @param mixed $human 一行 `user_infos`,没有传 null
  29. * @param mixed $assistant 一行 `ai_models`,没有传 null
  30. * @return array<string, mixed>
  31. */
  32. protected function actor($human, $assistant = null): array
  33. {
  34. return app(UserService::class)->actor($human, $assistant);
  35. }
  36. }