Pārlūkot izejas kodu

refactor(farm): 重构土地升级功能的验证逻辑

- 新增多个专门的验证器,分别负责土地状态、房屋等级、特殊土地数量等验证
- 优化验证流程,提高代码可读性和可维护性
- 移除冗余的逻辑判断,简化验证规则
- 增加错误日志记录,提高异常处理能力
notfff 7 mēneši atpakaļ
vecāks
revīzija
b6e755ca1d

+ 17 - 47
app/Module/AppGame/Handler/Land/RemoveCropHandler.php

@@ -15,6 +15,7 @@ use UCore\Exception\LogicException;
 
 /**
  * 处理铲除作物操作请求
+ * RemoveCrop
  */
 class RemoveCropHandler extends BaseHandler
 {
@@ -34,22 +35,23 @@ class RemoveCropHandler extends BaseHandler
     {
         // 创建响应对象
         $response = new ResponseLandRemoveCrop();
+        // 获取请求参数
+        $landId = $data->getLandId();
+        $toolItemId = $data->getItemId() ?? 0; // 铲除工具ID,可选
+        $userId = $this->user_id;
 
-        try {
-            // 获取请求参数
-            $landId = $data->getLandId();
-            $toolItemId = $data->getUserItemId() ?? 0; // 铲除工具ID,可选
-            $userId = $this->user_id;
+        // 先进行验证,避免不必要的事务开销
+        $validation = new CropRemoveValidation([
+                                                   'user_id' => $userId,
+                                                   'land_id' => $landId,
+                                                   'tool_item_id' => $toolItemId
+                                               ]);
 
-            // 先进行验证,避免不必要的事务开销
-            $validation = new CropRemoveValidation([
-                'user_id' => $userId,
-                'land_id' => $landId,
-                'tool_item_id' => $toolItemId
-            ]);
+        // 验证数据
+        $validation->validated();
+
+        try {
 
-            // 验证数据
-            $validation->validated();
 
             // 验证通过后,开启事务
             DB::beginTransaction();
@@ -72,45 +74,13 @@ class RemoveCropHandler extends BaseHandler
             // 提交事务
             DB::commit();
 
-            // 设置响应状态
-            $this->response->setCode(0);
-            $this->response->setMsg('铲除作物成功');
-
             Log::info('用户铲除作物成功', [
                 'user_id' => $userId,
                 'land_id' => $landId,
                 'tool_item_id' => $toolItemId
             ]);
 
-        } catch (\UCore\Exception\ValidateException $e) {
-            // 验证失败,此时可能还没有开启事务
-            $this->response->setCode(400);
-            $this->response->setMsg($e->getMessage());
-
-            Log::warning('铲除作物验证失败', [
-                'user_id' => $userId ?? null,
-                'land_id' => $landId ?? null,
-                'tool_item_id' => $toolItemId ?? null,
-                'error' => $e->getMessage()
-            ]);
-
-        } catch (LogicException $e) {
-            // 业务逻辑异常,需要回滚事务
-            if (DB::transactionLevel() > 0) {
-                DB::rollBack();
-            }
-
-            $this->response->setCode(400);
-            $this->response->setMsg($e->getMessage());
-
-            Log::warning('用户铲除作物失败', [
-                'user_id' => $userId ?? null,
-                'land_id' => $landId ?? null,
-                'tool_item_id' => $toolItemId ?? null,
-                'error' => $e->getMessage()
-            ]);
-
-        } catch (\Exception $e) {
+        }  catch (\Exception $e) {
             // 系统异常,需要回滚事务
             if (DB::transactionLevel() > 0) {
                 DB::rollBack();
@@ -130,4 +100,4 @@ class RemoveCropHandler extends BaseHandler
 
         return $response;
     }
-}
+}

+ 20 - 38
app/Module/AppGame/Handler/Land/UpHandler.php

@@ -36,25 +36,25 @@ class UpHandler extends BaseHandler
         // 创建响应对象
         $response = new ResponseLandUp();
 
+        // 获取请求参数
+        $landId = $data->getLandId();
+        $userId = $this->user_id;
+
+        // 先进行验证,避免不必要的事务开销
+        $validation = new LandUpgradeValidation([
+                                                    'user_id' => $userId,
+                                                    'land_id' => $landId
+                                                ]);
+
+        // 验证数据
+        $validation->validated();
+
+        // 从验证结果中获取升级配置和土地信息
+        $upgradeConfig = $validation->upgrade_config;
+        $land          = $validation->land;
+        $targetType    = $upgradeConfig->to_type_id;
+        dd($validation);
         try {
-            // 获取请求参数
-            $landId = $data->getLandId();
-            $userId = $this->user_id;
-
-            // 先进行验证,避免不必要的事务开销
-            $validation = new LandUpgradeValidation([
-                'user_id' => $userId,
-                'land_id' => $landId
-            ]);
-
-            // 验证数据
-            $validation->validated();
-
-            // 从验证结果中获取升级配置和土地信息
-            $upgradeConfig = $validation->upgrade_config;
-            $land = $validation->land;
-            $targetType = $upgradeConfig->to_type_id;
-
             // 验证通过后,开启事务
             DB::beginTransaction();
 
@@ -76,24 +76,6 @@ class UpHandler extends BaseHandler
                 'new_type' => $targetType
             ]);
 
-        } catch (\UCore\Exception\ValidateException $e) {
-            // 验证失败,此时可能还没有开启事务
-            throw new LogicException($e->getMessage());
-
-        } catch (LogicException $e) {
-            // 业务逻辑异常,需要回滚事务
-            if (DB::transactionLevel() > 0) {
-                DB::rollBack();
-            }
-
-            Log::warning('用户土地升级失败', [
-                'user_id' => $userId,
-                'land_id' => $landId ?? null,
-                'error' => $e->getMessage()
-            ]);
-
-            throw $e;
-
         } catch (\Exception $e) {
             // 系统异常,需要回滚事务
             if (DB::transactionLevel() > 0) {
@@ -103,8 +85,8 @@ class UpHandler extends BaseHandler
             Log::error('用户土地升级系统异常', [
                 'user_id' => $userId,
                 'land_id' => $landId ?? null,
-                'error' => $e->getMessage(),
-                'trace' => $e->getTraceAsString()
+                'error'   => $e->getMessage(),
+                'trace'   => $e->getTraceAsString()
             ]);
 
             throw new LogicException('系统异常,请稍后重试');

+ 16 - 19
app/Module/Farm/Logics/LandLogic.php

@@ -135,7 +135,7 @@ class LandLogic
 
     /**
      * 升级土地
-     * 调用前已经检查,确保用户有足够的材料,且已经检查了升级路径
+     * 调用前必须已经完成所有验证(土地归属、状态、路径、材料等)
      * 要求调用者已开启事务
      *
      * @param int $userId
@@ -156,32 +156,29 @@ class LandLogic
             ->where('user_id', $userId)
             ->first();
 
+        // 防错误机制:基础数据检查
         if (!$land) {
-            throw new LogicException('土地不存在');
+            throw new LogicException('Logic层防错误:土地不存在,验证层应该已经检查过');
         }
 
-        // 检查路径可用(不检查材料,因为调用前已验证)
-        $check = self::checkUpgradePath($userId, $land->land_type, $targetType, false);
-        if ($check->error) {
-            throw new LogicException('升级路径检查不通过!');
+        // 防错误机制:状态检查
+        if ($land->status !== LAND_STATUS::IDLE->value) {
+            throw new LogicException('Logic层防错误:土地状态不允许升级,验证层应该已经检查过');
         }
-        /**
-         *
-         * @var FarmLandUpgradeConfig $config
-         */
-        $config = $check->data['config'];
 
-        // 检查土地状态
-        if ($land->status !== LAND_STATUS::IDLE->value) {
-            throw new LogicException('土地状态不允许升级');
+        // 防错误机制:类型检查
+        if ($land->land_type === $targetType) {
+            throw new LogicException('Logic层防错误:土地已经是目标类型,验证层应该已经检查过');
         }
 
-        // 获取当前土地类型
-        $currentType = $land->land_type;
+        // 获取升级配置(这里不再进行完整验证,只获取配置)
+        $config = FarmLandUpgradeConfig::where('from_type_id', $land->land_type)
+            ->where('to_type_id', $targetType)
+            ->first();
 
-        // 检查是否已经是目标类型
-        if ($currentType === $targetType) {
-            throw new LogicException('土地已经是目标类型');
+        // 防错误机制:配置检查
+        if (!$config) {
+            throw new LogicException('Logic层防错误:升级配置不存在,验证层应该已经检查过');
         }
 
         // 更新土地类型

+ 6 - 1
app/Module/Farm/Validations/CropPlantValidation.php

@@ -10,11 +10,16 @@ use UCore\ValidationCore;
 
 /**
  * 作物种植验证类
- * 
+ *
  * 用于验证作物种植操作的输入数据,包括用户ID、土地ID、种子ID等
  */
 class CropPlantValidation extends ValidationCore
 {
+    /** @var \App\Module\Farm\Models\FarmLand|null 土地对象,由 LandOwnershipValidator 设置 */
+    public ?\App\Module\Farm\Models\FarmLand $land = null;
+
+    /** @var \App\Module\GameItems\Models\Item|null 种子物品对象,由 SeedItemValidator 设置 */
+    public ?\App\Module\GameItems\Models\Item $seed_item = null;
     /**
      * 验证规则
      *

+ 3 - 1
app/Module/Farm/Validations/HouseUpgradeValidation.php

@@ -7,11 +7,13 @@ use UCore\ValidationCore;
 
 /**
  * 房屋升级验证类
- * 
+ *
  * 用于验证房屋升级操作的输入数据,包括用户ID
  */
 class HouseUpgradeValidation extends ValidationCore
 {
+    /** @var \App\Module\Farm\Models\FarmHouseConfig|null 房屋配置对象,由 HouseUpgradeValidator 设置 */
+    public ?\App\Module\Farm\Models\FarmHouseConfig $house_config = null;
     /**
      * 验证规则
      *

+ 25 - 1
app/Module/Farm/Validations/LandUpgradeValidation.php

@@ -5,15 +5,24 @@ namespace App\Module\Farm\Validations;
 use App\Module\Farm\Validators\LandOwnershipValidator;
 use App\Module\Farm\Validators\LandUpgradePathValidator;
 use App\Module\Farm\Validators\LandUpgradeMaterialsValidator;
+use App\Module\Farm\Validators\LandUpgradeStatusValidator;
+use App\Module\Farm\Validators\LandUpgradeHouseLevelValidator;
+use App\Module\Farm\Validators\LandUpgradeSpecialLimitValidator;
 use UCore\ValidationCore;
 
 /**
  * 土地升级验证类
- * 
+ *
  * 用于验证土地升级操作的输入数据,包括用户ID、土地ID和目标类型
+ *
  */
 class LandUpgradeValidation extends ValidationCore
 {
+    /** @var \App\Module\Farm\Models\FarmLand|null 土地对象,由 LandOwnershipValidator 设置 */
+    public ?\App\Module\Farm\Models\FarmLand $land = null;
+
+    /** @var \App\Module\Farm\Models\FarmLandUpgradeConfig|null 升级配置,由 LandUpgradePathValidator 设置 */
+    public ?\App\Module\Farm\Models\FarmLandUpgradeConfig $upgrade_config = null;
     /**
      * 验证规则
      *
@@ -35,11 +44,26 @@ class LandUpgradeValidation extends ValidationCore
                 'land_id', new LandOwnershipValidator($this, ['user_id', 'land']),
                 'msg' => '土地不存在或不属于当前用户'
             ],
+            // 验证土地状态是否允许升级
+            [
+                'land_id', new LandUpgradeStatusValidator($this, ['land']),
+                'msg' => '土地状态不允许升级'
+            ],
             // 验证升级路径是否可用
             [
                 'land_id', new LandUpgradePathValidator($this, ['user_id', 'upgrade_config']),
                 'msg' => '升级路径验证失败'
             ],
+            // 验证房屋等级是否满足要求
+            [
+                'land_id', new LandUpgradeHouseLevelValidator($this, ['user_id', 'upgrade_config']),
+                'msg' => '房屋等级不足'
+            ],
+            // 验证特殊土地数量限制
+            [
+                'land_id', new LandUpgradeSpecialLimitValidator($this, ['user_id', 'upgrade_config']),
+                'msg' => '特殊土地数量已达上限'
+            ],
             // 验证升级材料是否足够
             [
                 'land_id', new LandUpgradeMaterialsValidator($this, ['user_id', 'upgrade_config']),

+ 1 - 0
app/Module/Farm/Validations/README.md

@@ -0,0 +1 @@
+# Validation 

+ 76 - 0
app/Module/Farm/Validators/LandUpgradeHouseLevelValidator.php

@@ -0,0 +1,76 @@
+<?php
+
+namespace App\Module\Farm\Validators;
+
+use App\Module\Farm\Models\FarmLandType;
+use App\Module\Farm\Models\FarmUser;
+use Illuminate\Support\Facades\Log;
+use UCore\Validator;
+
+/**
+ * 土地升级房屋等级验证器
+ * 
+ * 验证用户房屋等级是否满足土地升级要求
+ */
+class LandUpgradeHouseLevelValidator extends Validator
+{
+    /**
+     * 验证房屋等级
+     *
+     * @param mixed $value 土地ID
+     * @param array $data 包含用户ID的数组
+     * @return bool 验证是否通过
+     */
+    public function validate(mixed $value, array $data): bool
+    {
+        // 从 args 获取参数
+        $userIdKey = $this->args[0] ?? 'user_id';
+        $upgradeConfigKey = $this->args[1] ?? 'upgrade_config';
+        
+        $userId = $data[$userIdKey] ?? null;
+        $upgradeConfig = $this->validation->$upgradeConfigKey ?? null;
+
+        if (!$userId) {
+            $this->addError('用户ID不能为空');
+            return false;
+        }
+
+        if (!$upgradeConfig) {
+            $this->addError('升级配置不存在,请先验证升级路径');
+            return false;
+        }
+
+        try {
+            // 获取目标土地类型
+            $targetLandType = FarmLandType::find($upgradeConfig->to_type_id);
+            if (!$targetLandType) {
+                $this->addError('目标土地类型不存在');
+                return false;
+            }
+
+            // 获取用户房屋信息
+            $farmUser = FarmUser::where('user_id', $userId)->first();
+            if (!$farmUser) {
+                $this->addError('用户农场信息不存在');
+                return false;
+            }
+
+            // 检查房屋等级是否满足要求
+            if ($farmUser->house_level < $targetLandType->unlock_house_level) {
+                $this->addError("房屋等级不足,需要{$targetLandType->unlock_house_level}级,当前{$farmUser->house_level}级");
+                return false;
+            }
+
+            return true;
+        } catch (\Exception $e) {
+            Log::error('验证房屋等级时发生错误', [
+                'user_id' => $userId,
+                'error' => $e->getMessage(),
+                'trace' => $e->getTraceAsString()
+            ]);
+            
+            $this->addError('验证房屋等级时发生错误: ' . $e->getMessage());
+            return false;
+        }
+    }
+}

+ 14 - 18
app/Module/Farm/Validators/LandUpgradePathValidator.php

@@ -2,14 +2,13 @@
 
 namespace App\Module\Farm\Validators;
 
-use App\Module\Farm\Logics\LandLogic;
 use App\Module\Farm\Models\FarmLand;
 use App\Module\Farm\Services\LandService;
 use UCore\Validator;
 
 /**
  * 土地升级路径验证器
- * 
+ *
  * 验证土地是否有可用的升级路径
  */
 class LandUpgradePathValidator extends Validator
@@ -24,7 +23,7 @@ class LandUpgradePathValidator extends Validator
     public function validate(mixed $value, array $data): bool
     {
         $landId = (int)$value;
-        
+
         // 从 args 获取用户ID的键名,默认为 'user_id'
         $userIdKey = $this->args[0] ?? 'user_id';
         $userId = $data[$userIdKey] ?? null;
@@ -37,7 +36,7 @@ class LandUpgradePathValidator extends Validator
         try {
             // 获取可用的升级路径
             $upgradePaths = LandService::getAvailableUpgradePaths($userId, $landId);
-            
+
             if (empty($upgradePaths)) {
                 $this->addError('当前没有可用的升级路径');
                 return false;
@@ -45,34 +44,31 @@ class LandUpgradePathValidator extends Validator
 
             // 选择第一个可用的升级路径
             $upgradePath = $upgradePaths[0];
-            
-            // 获取土地信息进行二次验证
+
+            // 获取土地信息
             $land = FarmLand::where('id', $landId)
                 ->where('user_id', $userId)
                 ->first();
-                
+
             if (!$land) {
                 $this->addError('土地不存在');
                 return false;
             }
 
-            // 验证升级路径的有效性
-            $checkResult = LandLogic::checkUpgradePath(
-                $userId, 
-                $land->land_type, 
-                $upgradePath['to_type_id'], 
-                false // 不检查材料,材料检查由专门的验证器处理
-            );
-            
-            if ($checkResult->error) {
-                $this->addError($checkResult->message);
+            // 获取升级配置(只检查配置是否存在,不进行其他验证)
+            $upgradeConfig = \App\Module\Farm\Models\FarmLandUpgradeConfig::where('from_type_id', $land->land_type)
+                ->where('to_type_id', $upgradePath['to_type_id'])
+                ->first();
+
+            if (!$upgradeConfig) {
+                $this->addError('升级配置不存在');
                 return false;
             }
 
             // 将升级配置保存到验证对象中,供后续使用
             $upgradeConfigKey = $this->args[1] ?? null;
             if ($upgradeConfigKey) {
-                $this->validation->$upgradeConfigKey = $checkResult->data['config'];
+                $this->validation->$upgradeConfigKey = $upgradeConfig;
             }
 
             return true;

+ 99 - 0
app/Module/Farm/Validators/LandUpgradeSpecialLimitValidator.php

@@ -0,0 +1,99 @@
+<?php
+
+namespace App\Module\Farm\Validators;
+
+use App\Module\Farm\Enums\LAND_TYPE;
+use App\Module\Farm\Models\FarmLand;
+use App\Module\Farm\Models\FarmLandType;
+use App\Module\Farm\Models\FarmUser;
+use Illuminate\Support\Facades\Log;
+use UCore\Validator;
+
+/**
+ * 土地升级特殊土地数量限制验证器
+ * 
+ * 验证特殊土地数量是否已达上限
+ */
+class LandUpgradeSpecialLimitValidator extends Validator
+{
+    /**
+     * 验证特殊土地数量限制
+     *
+     * @param mixed $value 土地ID
+     * @param array $data 包含用户ID的数组
+     * @return bool 验证是否通过
+     */
+    public function validate(mixed $value, array $data): bool
+    {
+        // 从 args 获取参数
+        $userIdKey = $this->args[0] ?? 'user_id';
+        $upgradeConfigKey = $this->args[1] ?? 'upgrade_config';
+        
+        $userId = $data[$userIdKey] ?? null;
+        $upgradeConfig = $this->validation->$upgradeConfigKey ?? null;
+
+        if (!$userId) {
+            $this->addError('用户ID不能为空');
+            return false;
+        }
+
+        if (!$upgradeConfig) {
+            $this->addError('升级配置不存在,请先验证升级路径');
+            return false;
+        }
+
+        try {
+            // 获取目标土地类型
+            $targetLandType = FarmLandType::find($upgradeConfig->to_type_id);
+            if (!$targetLandType) {
+                $this->addError('目标土地类型不存在');
+                return false;
+            }
+
+            // 如果不是特殊土地,直接通过验证
+            if (!$targetLandType->is_special) {
+                return true;
+            }
+
+            // 获取用户农场信息
+            $farmUser = FarmUser::where('user_id', $userId)->first();
+            if (!$farmUser) {
+                $this->addError('用户农场信息不存在');
+                return false;
+            }
+
+            // 获取用户当前特殊土地数量
+            $specialLandCount = FarmLand::where('user_id', $userId)
+                ->whereIn('land_type', [
+                    LAND_TYPE::GOLD->value,
+                    LAND_TYPE::BLUE->value,
+                    LAND_TYPE::PURPLE->value
+                ])
+                ->count();
+
+            // 获取房屋配置
+            $houseConfig = $farmUser->houseConfig;
+            if (!$houseConfig) {
+                $this->addError('房屋配置不存在');
+                return false;
+            }
+
+            // 检查特殊土地数量限制
+            if ($specialLandCount >= $houseConfig->special_land_limit) {
+                $this->addError("特殊土地数量已达上限({$houseConfig->special_land_limit}块),当前已有{$specialLandCount}块");
+                return false;
+            }
+
+            return true;
+        } catch (\Exception $e) {
+            Log::error('验证特殊土地数量限制时发生错误', [
+                'user_id' => $userId,
+                'error' => $e->getMessage(),
+                'trace' => $e->getTraceAsString()
+            ]);
+            
+            $this->addError('验证特殊土地数量限制时发生错误: ' . $e->getMessage());
+            return false;
+        }
+    }
+}

+ 74 - 0
app/Module/Farm/Validators/LandUpgradeStatusValidator.php

@@ -0,0 +1,74 @@
+<?php
+
+namespace App\Module\Farm\Validators;
+
+use App\Module\Farm\Enums\LAND_STATUS;
+use UCore\Validator;
+
+/**
+ * 土地升级状态验证器
+ *
+ * 验证土地状态是否允许进行升级操作
+ */
+class LandUpgradeStatusValidator extends Validator
+{
+    /**
+     * 验证土地升级状态
+     *
+     * @param mixed $value 土地ID
+     * @param array $data 包含其他数据的数组
+     * @return bool 验证是否通过
+     */
+    public function validate(mixed $value, array $data): bool
+    {
+        // 从 args 获取土地对象的键名
+        $landKey = $this->args[0] ?? 'land';
+        $land = $this->validation->$landKey ?? null;
+
+
+
+        if (!$land) {
+            $this->addError('土地信息不存在,请先验证土地归属');
+            return false;
+        }
+
+        try {
+            // 检查土地状态是否为空闲状态(允许升级)
+            // 只有空闲状态的土地才能进行升级
+            if ($land->status !== LAND_STATUS::IDLE->value) {
+                $statusName = $this->getStatusName($land->status);
+                $errorMsg = "土地当前状态为{$statusName},不允许升级";
+
+
+
+                $this->addError($errorMsg);
+                return false;
+            }
+
+
+
+            return true;
+        } catch (\Exception $e) {
+            $this->addError('验证土地升级状态时发生错误: ' . $e->getMessage());
+            return false;
+        }
+    }
+
+    /**
+     * 获取状态名称
+     *
+     * @param int $status 状态值
+     * @return string 状态名称
+     */
+    private function getStatusName(int $status): string
+    {
+        return match ($status) {
+            LAND_STATUS::IDLE->value => '空闲',
+            LAND_STATUS::PLANTING->value => '种植中',
+            LAND_STATUS::HARVESTABLE->value => '可收获',
+            LAND_STATUS::WITHERED->value => '枯萎',
+            LAND_STATUS::DISASTER->value => '灾害',
+            default => '未知状态'
+        };
+    }
+}

+ 1 - 0
app/Module/Farm/Validators/README.md

@@ -0,0 +1 @@
+# Validator