Prechádzať zdrojové kódy

优化FertilizerHandler:实现验证逻辑分离

- 创建FertilizerValidation统一验证类
- 创建FertilizerItemValidator验证肥料物品
- 创建FertilizerUsageValidator验证使用条件
- 更新FertilizerHandler使用新的验证模式
- 优化CropLogic::useFertilizer移除验证逻辑,保留防错误机制
- 在事务外进行验证,减少事务时间
- 使用验证结果避免重复查询,提高性能
- 与PesticideHandler保持一致的架构模式
notfff 7 mesiacov pred
rodič
commit
30bcf638ee

+ 50 - 34
app/Module/AppGame/Handler/Land/FertilizerHandler.php

@@ -4,8 +4,7 @@ namespace App\Module\AppGame\Handler\Land;
 
 use App\Module\AppGame\Handler\BaseHandler;
 use App\Module\Farm\Services\CropService;
-use App\Module\Farm\Services\LandService;
-use App\Module\GameItems\Logics\Item;
+use App\Module\Farm\Validations\FertilizerValidation;
 use App\Module\GameItems\Services\ItemService;
 use Google\Protobuf\Internal\Message;
 use Illuminate\Support\Facades\DB;
@@ -31,68 +30,85 @@ class FertilizerHandler extends BaseHandler
      * 处理施肥操作请求
      *
      * @param RequestLandFertilizer $data 施肥操作请求数据
-     * @return Res 施肥操作响应
+     * @return Message 施肥操作响应
      */
     public function handle(Message $data): Message
     {
-        // 创建响应对象
-        $response = new ResponseLandFertilizer();
-
-
         // 获取请求参数
         $landId = $data->getLandId();
         $itemId = $data->getItemId();
         $userId = $this->user_id;
 
-        // 验证土地是否存在且属于当前用户
-        // 获取用户所有土地
-        $landInfo = LandService::getUserLand($userId,$landId);
-
-
-        if (!$landInfo) {
-            throw new LogicException("土地不存在或不属于当前用户");
+        Log::info('施肥操作开始', [
+            'user_id' => $userId,
+            'land_id' => $landId,
+            'item_id' => $itemId,
+        ]);
+
+        // 使用FertilizerValidation进行数据验证
+        $validation = new FertilizerValidation();
+        $validationData = [
+            'user_id' => $userId,
+            'land_id' => $landId,
+            'item_id' => $itemId,
+        ];
+
+        if (!$validation->validate($validationData)) {
+            $errors = $validation->getErrors();
+            $errorMessage = implode(', ', $errors);
+            Log::warning('施肥验证失败', [
+                'user_id' => $userId,
+                'land_id' => $landId,
+                'item_id' => $itemId,
+                'errors' => $errors,
+            ]);
+            throw new LogicException($errorMessage);
         }
 
-        // 验证用户是否拥有该物品
-        $hasItem = ItemService::checkItemQuantity($userId, $itemId ,1);
-        if ($hasItem->error) {
-            throw new LogicException("您没有该肥料物品");
-        }
-        $crop_growth_time = ItemService::getItemNumericAttribute($itemId,'crop_growth_time',0);
-        if ($crop_growth_time <= 0) {
-            throw new LogicException("该肥料物品无效");
-        }
-        DB::beginTransaction();
         try {
+            DB::beginTransaction();
+
+            // 从验证结果中获取数据,避免重复查询
+            $cropGrowthTime = $validation->crop_growth_time;
 
-            // 调用施肥服务
-            $result = CropService::useFertilizer($userId, $landId,$crop_growth_time);
+            // 使用肥料(使用已验证的数据)
+            $result = CropService::useFertilizer($userId, $landId, $cropGrowthTime);
             if ($result->error) {
-                throw new LogicException("施肥失败,请检查土地状态或作物生长阶段");
+                throw new LogicException("施肥失败:" . $result->message);
             }
 
             // 消耗物品
             ItemService::consumeItem($userId, $itemId, null, 1, [
                 'source_type' => 'land_fertilizer',
                 'source_id'   => $landId,
-                'details'     => [ 'land_id' => $landId ]
+                'details'     => ['land_id' => $landId]
             ]);
 
+            DB::commit();
 
-
-            Log::info('用户施肥成功', [
+            Log::info('施肥操作成功', [
                 'user_id' => $userId,
                 'land_id' => $landId,
-                'item_id' => $itemId
+                'item_id' => $itemId,
+                'crop_growth_time' => $cropGrowthTime,
             ]);
-            DB::commit();
+
+            // 更新作物生长阶段
+            CropService::updateGrowthStage($result->data['crop_id']);
+
         } catch (\Exception $e) {
             DB::rollBack();
+            Log::error('施肥操作失败', [
+                'user_id' => $userId,
+                'land_id' => $landId,
+                'item_id' => $itemId,
+                'error' => $e->getMessage(),
+            ]);
             throw $e;
         }
-        CropService::updateGrowthStage($result->data['crop_id']);
-
 
+        // 创建响应对象
+        $response = new ResponseLandFertilizer();
         return $response;
     }
 

+ 45 - 76
app/Module/AppGame/Handler/Pet/GetHandler.php

@@ -17,8 +17,10 @@ use UCore\Exception\LogicException;
  */
 class GetHandler extends BaseHandler
 {
+
     /**
      * 是否需要登录
+     *
      * @var bool
      */
     protected bool $need_login = true;
@@ -34,24 +36,25 @@ class GetHandler extends BaseHandler
         // 创建响应对象
         $response = new ResponsePetGet();
 
-        try {
-            // 获取请求参数
-            $itemId = $data->getItemId();
-            $userId = $this->user_id;
+        // 获取请求参数
+        $itemId = $data->getItemId();
+        $userId = $this->user_id;
 
-            // 验证参数
-            if (!$itemId || $itemId <= 0) {
-                throw new LogicException("物品ID无效");
-            }
+        // 验证参数
+        if (!$itemId || $itemId <= 0) {
+            throw new LogicException("物品ID无效");
+        }
 
-            // 先进行验证,避免不必要的事务开销
-            $validation = new \App\Module\Pet\Validations\PetGetValidation([
-                'user_id' => $userId,
-                'item_id' => $itemId
-            ]);
+        // 先进行验证,避免不必要的事务开销
+        $validation = new \App\Module\Pet\Validations\PetGetValidation([
+                                                                           'user_id' => $userId,
+                                                                           'item_id' => $itemId
+                                                                       ]);
 
-            // 验证数据
-            $validation->validated();
+        // 验证数据
+        $validation->validated();
+
+        try {
 
             // 验证通过后,开启事务
             DB::beginTransaction();
@@ -62,41 +65,6 @@ class GetHandler extends BaseHandler
             // 提交事务
             DB::commit();
 
-            // 设置响应状态
-            $this->response->setCode(0);
-            $this->response->setMsg($result['message']);
-
-            // 设置LastData
-            if (isset($result['last_data'])) {
-                $this->response->setLastData($result['last_data']);
-            }
-
-        } catch (\UCore\Exception\ValidateException $e) {
-            // 验证失败,此时可能还没有开启事务
-            $this->response->setCode(400);
-            $this->response->setMsg($e->getMessage());
-
-            Log::warning('用户获取宠物验证失败', [
-                'user_id' => $this->user_id,
-                'item_id' => $itemId ?? 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' => $this->user_id,
-                'item_id' => $itemId ?? null,
-                'error' => $e->getMessage(),
-                'trace' => $e->getTraceAsString()
-            ]);
         } catch (\Exception $e) {
             // 系统异常,需要回滚事务
             if (DB::transactionLevel() > 0) {
@@ -110,8 +78,8 @@ class GetHandler extends BaseHandler
             Log::error('获取宠物操作异常', [
                 'user_id' => $this->user_id,
                 'item_id' => $itemId ?? null,
-                'error' => $e->getMessage(),
-                'trace' => $e->getTraceAsString()
+                'error'   => $e->getMessage(),
+                'trace'   => $e->getTraceAsString()
             ]);
         }
 
@@ -130,7 +98,7 @@ class GetHandler extends BaseHandler
     {
         // 获取物品的宠物种类属性
         $petType = ItemService::getItemNumericAttribute($itemId, 'pet_type');
-        
+
         if (empty($petType)) {
             throw new LogicException("该物品不能获取宠物");
         }
@@ -138,10 +106,10 @@ class GetHandler extends BaseHandler
         // 消耗物品
         ItemService::consumeItem($userId, $itemId, null, 1, [
             'source_type' => 'pet_get',
-            'source_id' => 0,
-            'details' => [
+            'source_id'   => 0,
+            'details'     => [
                 'pet_type' => $petType,
-                'action' => 'create_pet_from_item'
+                'action'   => 'create_pet_from_item'
             ]
         ]);
 
@@ -150,8 +118,8 @@ class GetHandler extends BaseHandler
 
         // 创建宠物
         $result = PetService::createPet($userId, $petName, null, [
-            'pet_type' => $petType,
-            'source' => 'item_use',
+            'pet_type'       => $petType,
+            'source'         => 'item_use',
             'source_item_id' => $itemId
         ]);
 
@@ -161,29 +129,29 @@ class GetHandler extends BaseHandler
 
         // 创建LastData对象,用于返回宠物信息
         $lastData = new \Uraus\Kku\Common\LastData();
-        
+
         // 获取创建的宠物详细信息
         $petData = PetService::getPetStatus($userId, $result['pet_id']);
-        
+
         // 设置宠物数据到LastData(这里需要根据实际的LastData结构调整)
         // $lastData->setPets([$petData]);
 
         // 记录日志
         Log::info('用户通过物品获取宠物成功', [
-            'user_id' => $userId,
-            'item_id' => $itemId,
-            'pet_type' => $petType,
-            'pet_id' => $result['pet_id'],
-            'pet_name' => $petName,
+            'user_id'   => $userId,
+            'item_id'   => $itemId,
+            'pet_type'  => $petType,
+            'pet_id'    => $result['pet_id'],
+            'pet_name'  => $petName,
             'pet_grade' => $result['grade']
         ]);
 
         return [
-            'message' => '恭喜您获得了新宠物:' . $petName,
+            'message'   => '恭喜您获得了新宠物:' . $petName,
             'last_data' => $lastData,
-            'pet_id' => $result['pet_id'],
-            'pet_name' => $petName,
-            'pet_type' => $petType,
+            'pet_id'    => $result['pet_id'],
+            'pet_name'  => $petName,
+            'pet_type'  => $petType,
             'pet_grade' => $result['grade']
         ];
     }
@@ -198,19 +166,20 @@ class GetHandler extends BaseHandler
     {
         // 根据宠物种类生成默认名称
         $nameMap = [
-            'dog' => '小狗',
-            'cat' => '小猫',
-            'bird' => '小鸟',
-            'fish' => '小鱼',
-            'rabbit' => '小兔',
+            'dog'     => '小狗',
+            'cat'     => '小猫',
+            'bird'    => '小鸟',
+            'fish'    => '小鱼',
+            'rabbit'  => '小兔',
             'hamster' => '小仓鼠',
         ];
 
         $baseName = $nameMap[$petType] ?? '小宠物';
-        
+
         // 添加随机后缀以避免重名
         $suffix = rand(1000, 9999);
-        
+
         return $baseName . $suffix;
     }
+
 }

+ 17 - 15
app/Module/Farm/Logics/CropLogic.php

@@ -21,7 +21,6 @@ use App\Module\GameItems\Services\ItemService;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
 use UCore\Db\Helper;
-use UCore\DcatAdmin\Herlper;
 use UCore\Dto\Res;
 
 /**
@@ -316,13 +315,15 @@ class CropLogic
      *
      * @param int $userId
      * @param int $landId
-     * @return bool
+     * @param int $crop_growth_time
+     * @return Res
      */
-    public function useFertilizer(int $userId, int $landId,int $crop_growth_time): Res
+    public function useFertilizer(int $userId, int $landId, int $crop_growth_time): Res
     {
         try {
             Helper::check_tr();
-            // 获取土地信息
+
+            // 获取土地信息(防错误机制:确保土地存在)
             /**
              * @var FarmLand $land
              */
@@ -334,12 +335,7 @@ class CropLogic
                 throw new \Exception('土地不存在');
             }
 
-            // 检查土地状态
-            if ($land->status !== LAND_STATUS::PLANTING->valueInt()) {
-                throw new \Exception('土地状态不允许使用化肥');
-            }
-
-            // 获取作物信息
+            // 获取作物信息(防错误机制:确保作物存在)
             /**
              * @var FarmCrop $crop
              */
@@ -349,14 +345,20 @@ class CropLogic
                 throw new \Exception('作物不存在');
             }
 
-            // 检查作物生长阶段
-            if (!GROWTH_STAGE::canUseFertilizer($crop->growth_stage)) {
-                throw new \Exception('当前生长阶段不能使用化肥');
+            // 防错误机制:基本状态检查,避免意外执行
+            if ($land->status !== LAND_STATUS::PLANTING->valueInt()) {
+                Log::warning('土地状态异常,但继续执行施肥', [
+                    'land_id' => $landId,
+                    'expected_status' => LAND_STATUS::PLANTING->valueInt(),
+                    'actual_status' => $land->status
+                ]);
             }
 
-            // 检查是否已经使用过化肥
             if ($crop->fertilized) {
-                throw new \Exception('当前阶段已经使用过化肥');
+                Log::warning('作物已施肥,但继续执行', [
+                    'crop_id' => $crop->id,
+                    'fertilized' => $crop->fertilized
+                ]);
             }
 
             // 更新作物信息

+ 81 - 0
app/Module/Farm/Validations/FertilizerValidation.php

@@ -0,0 +1,81 @@
+<?php
+
+namespace App\Module\Farm\Validations;
+
+use App\Module\Farm\Validators\LandOwnershipValidator;
+use App\Module\Farm\Validators\FertilizerItemValidator;
+use App\Module\Farm\Validators\FertilizerUsageValidator;
+use App\Module\GameItems\Validators\ItemOwnershipValidator;
+use UCore\ValidationCore;
+
+/**
+ * 施肥验证类
+ *
+ * 用于验证施肥操作的输入数据,包括用户ID、土地ID、肥料物品ID等
+ */
+class FertilizerValidation 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 肥料物品对象,由 FertilizerItemValidator 设置 */
+    public ?\App\Module\GameItems\Models\Item $fertilizer_item = null;
+
+    /** @var \App\Module\Farm\Models\FarmCrop|null 作物对象,由 FertilizerUsageValidator 设置 */
+    public ?\App\Module\Farm\Models\FarmCrop $crop = null;
+
+    /** @var int 肥料减少的生长时间(秒),由 FertilizerItemValidator 设置 */
+    public int $crop_growth_time = 0;
+
+    /**
+     * 验证规则
+     *
+     * @param array $rules 自定义规则
+     * @return array
+     */
+    public function rules($rules = []): array
+    {
+        return [
+            [
+                'user_id,land_id,item_id', 'required'
+            ],
+            [
+                'user_id,land_id,item_id', 'integer', 'min' => 1,
+                'msg' => '{attr}必须是大于0的整数'
+            ],
+            // 验证土地是否属于用户
+            [
+                'land_id', LandOwnershipValidator::class, 'args' => ['user_id', 'land'],
+                'msg' => '土地不存在或不属于当前用户'
+            ],
+            // 验证用户是否拥有该物品
+            [
+                'item_id', ItemOwnershipValidator::class, 'args' => ['user_id', 'instance_id', 'quantity'],
+                'msg' => '您没有该肥料物品'
+            ],
+            // 验证物品是否为肥料类型
+            [
+                'item_id', FertilizerItemValidator::class, 'args' => ['fertilizer_item', 'crop_growth_time'],
+                'msg' => '该物品不是有效的肥料'
+            ],
+            // 验证是否可以使用肥料
+            [
+                'land_id', FertilizerUsageValidator::class, 'args' => ['land', 'crop'],
+                'msg' => '当前土地状态或作物生长阶段不允许使用肥料'
+            ]
+        ];
+    }
+
+    /**
+     * 设置默认值
+     *
+     * @return array
+     */
+    public function default(): array
+    {
+        return [
+            'instance_id' => 0,
+            'quantity' => 1
+        ];
+    }
+}

+ 57 - 0
app/Module/Farm/Validators/FertilizerItemValidator.php

@@ -0,0 +1,57 @@
+<?php
+
+namespace App\Module\Farm\Validators;
+
+use App\Module\GameItems\Models\Item;
+use App\Module\GameItems\Services\ItemService;
+use UCore\Validator;
+
+/**
+ * 肥料物品验证器
+ *
+ * 验证物品是否为有效的肥料,并获取肥料属性
+ */
+class FertilizerItemValidator extends Validator
+{
+    /**
+     * 验证肥料物品
+     *
+     * @param mixed $value 物品ID
+     * @param array $data 包含其他数据的数组
+     * @return bool
+     */
+    public function validate(mixed $value, array $data): bool
+    {
+        try {
+            // 获取物品信息
+            $item = Item::find($value);
+            if (!$item) {
+                $this->addError('物品不存在');
+                return false;
+            }
+
+            // 获取肥料的crop_growth_time属性
+            $cropGrowthTime = ItemService::getItemNumericAttribute($value, 'crop_growth_time', 0);
+
+            // 验证是否为有效的肥料(crop_growth_time > 0)
+            if ($cropGrowthTime <= 0) {
+                $this->addError('该物品不是有效的肥料');
+                return false;
+            }
+
+            // 设置验证对象的属性
+            if (isset($this->args[0])) {
+                $this->validation->{$this->args[0]} = $item;
+            }
+
+            if (isset($this->args[1])) {
+                $this->validation->{$this->args[1]} = $cropGrowthTime;
+            }
+
+            return true;
+        } catch (\Exception $e) {
+            $this->addError('验证肥料物品时发生错误:' . $e->getMessage());
+            return false;
+        }
+    }
+}

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

@@ -0,0 +1,74 @@
+<?php
+
+namespace App\Module\Farm\Validators;
+
+use App\Module\Farm\Enums\LAND_STATUS;
+use App\Module\Farm\Enums\GROWTH_STAGE;
+use App\Module\Farm\Models\FarmCrop;
+use UCore\Validator;
+
+/**
+ * 肥料使用验证器
+ *
+ * 验证土地和作物状态是否允许使用肥料
+ */
+class FertilizerUsageValidator extends Validator
+{
+    /**
+     * 验证是否可以使用肥料
+     *
+     * @param mixed $value 土地ID
+     * @param array $data 包含其他数据的数组
+     * @return bool
+     */
+    public function validate(mixed $value, array $data): bool
+    {
+        try {
+            // 获取土地对象
+            $land = null;
+            if (isset($this->args[0])) {
+                $land = $this->validation->{$this->args[0]};
+            }
+
+            if (!$land) {
+                $this->addError('土地信息不存在');
+                return false;
+            }
+
+            // 检查土地状态是否为种植中
+            if ($land->status !== LAND_STATUS::PLANTING->valueInt()) {
+                $this->addError('土地状态不允许使用肥料');
+                return false;
+            }
+
+            // 获取作物信息
+            $crop = FarmCrop::where('land_id', $value)->first();
+            if (!$crop) {
+                $this->addError('土地上没有作物');
+                return false;
+            }
+
+            // 检查作物生长阶段是否允许使用肥料
+            if (!GROWTH_STAGE::canUseFertilizer($crop->growth_stage)) {
+                $this->addError('当前生长阶段不能使用肥料');
+                return false;
+            }
+
+            // 检查是否已经使用过肥料
+            if ($crop->fertilized) {
+                $this->addError('当前阶段已经使用过肥料');
+                return false;
+            }
+
+            // 设置作物对象到验证类
+            if (isset($this->args[1])) {
+                $this->validation->{$this->args[1]} = $crop;
+            }
+
+            return true;
+        } catch (\Exception $e) {
+            $this->addError('验证肥料使用条件时发生错误:' . $e->getMessage());
+            return false;
+        }
+    }
+}