ItemQuantity.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. <?php
  2. namespace App\Module\GameItems\Logics;
  3. use App\Module\GameItems\Models\ItemUser;
  4. use Exception;
  5. /**
  6. * 物品数量逻辑类
  7. *
  8. * 提供物品数量相关的逻辑处理,支持普通物品和实例物品
  9. */
  10. class ItemQuantity
  11. {
  12. /**
  13. * 获取用户物品数量
  14. *
  15. * @param int $userId 用户ID
  16. * @param int $itemId 物品ID
  17. * @param bool $includeExpired 是否包含已过期物品
  18. * @return int 物品数量
  19. * @throws Exception 如果查询过程中发生错误
  20. */
  21. public static function getUserItemQuantity(int $userId, int $itemId, bool $includeExpired = false): int
  22. {
  23. try {
  24. $query = ItemUser::where('user_id', $userId)
  25. ->where('item_id', $itemId);
  26. // 排除过期物品
  27. if (!$includeExpired) {
  28. $now = now();
  29. $query->where(function ($q) use ($now) {
  30. $q->whereNull('expire_at')
  31. ->orWhere('expire_at', '>', $now);
  32. })->whereHas('item', function ($q) use ($now) {
  33. $q->where(function ($subQ) use ($now) {
  34. $subQ->whereNull('global_expire_at')
  35. ->orWhere('global_expire_at', '>', $now);
  36. });
  37. });
  38. }
  39. return $query->sum('quantity');
  40. } catch (Exception $e) {
  41. throw new Exception("获取用户物品数量失败: " . $e->getMessage(), 0, $e);
  42. }
  43. }
  44. /**
  45. * 获取用户实例物品数量
  46. *
  47. * @param int $userId 用户ID
  48. * @param int $itemId 物品ID
  49. * @param int|null $instanceId 实例ID,如果为null则获取所有实例
  50. * @param bool $includeExpired 是否包含已过期物品
  51. * @return int 物品数量
  52. * @throws Exception 如果查询过程中发生错误
  53. */
  54. public static function getUserInstanceItemQuantity(int $userId, int $itemId, ?int $instanceId = null, bool $includeExpired = false): int
  55. {
  56. try {
  57. $query = ItemUser::where('user_id', $userId)
  58. ->where('item_id', $itemId)
  59. ->whereNotNull('instance_id');
  60. // 如果指定了实例ID,则只查询该实例
  61. if ($instanceId !== null) {
  62. $query->where('instance_id', $instanceId);
  63. }
  64. // 排除过期物品
  65. if (!$includeExpired) {
  66. $now = now();
  67. $query->where(function ($q) use ($now) {
  68. $q->whereNull('expire_at')
  69. ->orWhere('expire_at', '>', $now);
  70. })->whereHas('item', function ($q) use ($now) {
  71. $q->where(function ($subQ) use ($now) {
  72. $subQ->whereNull('global_expire_at')
  73. ->orWhere('global_expire_at', '>', $now);
  74. });
  75. });
  76. }
  77. return $query->sum('quantity');
  78. } catch (Exception $e) {
  79. throw new Exception("获取用户实例物品数量失败: " . $e->getMessage(), 0, $e);
  80. }
  81. }
  82. /**
  83. * 获取用户物品总数量(包括普通物品和实例物品)
  84. *
  85. * @param int $userId 用户ID
  86. * @param int $itemId 物品ID
  87. * @param bool $includeExpired 是否包含已过期物品
  88. * @return int 物品总数量
  89. * @throws Exception 如果查询过程中发生错误
  90. */
  91. public static function getUserTotalItemQuantity(int $userId, int $itemId, bool $includeExpired = false): int
  92. {
  93. $normalQuantity = self::getUserItemQuantity($userId, $itemId, $includeExpired);
  94. $instanceQuantity = self::getUserInstanceItemQuantity($userId, $itemId, null, $includeExpired);
  95. return $normalQuantity + $instanceQuantity;
  96. }
  97. /**
  98. * 检查用户是否拥有足够数量的普通物品
  99. *
  100. * @param int $userId 用户ID
  101. * @param int $itemId 物品ID
  102. * @param int $quantity 需要的数量
  103. * @param bool $includeExpired 是否包含已过期物品
  104. * @return bool 是否拥有足够数量
  105. * @throws Exception 如果查询过程中发生错误
  106. */
  107. public static function hasEnoughItems(int $userId, int $itemId, int $quantity, bool $includeExpired = false): bool
  108. {
  109. $userQuantity = self::getUserItemQuantity($userId, $itemId, $includeExpired);
  110. return $userQuantity >= $quantity;
  111. }
  112. /**
  113. * 检查用户是否拥有指定的实例物品
  114. *
  115. * @param int $userId 用户ID
  116. * @param int $itemId 物品ID
  117. * @param int $instanceId 实例ID
  118. * @param bool $includeExpired 是否包含已过期物品
  119. * @return bool 是否拥有该实例物品
  120. * @throws Exception 如果查询过程中发生错误
  121. */
  122. public static function hasInstanceItem(int $userId, int $itemId, int $instanceId, bool $includeExpired = false): bool
  123. {
  124. $quantity = self::getUserInstanceItemQuantity($userId, $itemId, $instanceId, $includeExpired);
  125. return $quantity > 0;
  126. }
  127. /**
  128. * 检查用户是否拥有足够数量的物品(包括普通物品和实例物品)
  129. *
  130. * @param int $userId 用户ID
  131. * @param int $itemId 物品ID
  132. * @param int $quantity 需要的数量
  133. * @param bool $includeExpired 是否包含已过期物品
  134. * @return bool 是否拥有足够数量
  135. * @throws Exception 如果查询过程中发生错误
  136. */
  137. public static function hasEnoughTotalItems(int $userId, int $itemId, int $quantity, bool $includeExpired = false): bool
  138. {
  139. $totalQuantity = self::getUserTotalItemQuantity($userId, $itemId, $includeExpired);
  140. return $totalQuantity >= $quantity;
  141. }
  142. }