You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免Laravel API控制器中重复的相似代码?

避免Laravel控制器重复代码的几种实用方案

针对你目前控制器中大量重复的列表查询与响应逻辑,可以通过以下几种方式简化代码:

1. 提取通用私有方法

在控制器内部封装一个通用的资源列表获取方法,将模型类和响应键作为参数传入,避免重复编写try-catch和响应结构:

use App\Models\AccountStatus;
use App\Models\AccountType;
use App\Models\AlertLevel;

class ClientController extends Controller
{
    /**
     * 获取指定模型的列表并返回统一格式响应
     * @param string $modelClass 模型类全名
     * @param string $responseKey 响应中的数据键名
     * @return \Illuminate\Http\JsonResponse
     */
    private function getResourceList($modelClass, $responseKey)
    {
        try {
            $data = $modelClass::all();
            return response()->json([
                'error' => false,
                'message' => 'OK',
                $responseKey => $data
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'error' => true,
                'message' => $e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine()
            ], 500);
        }
    }

    public function getAccountStatuses()
    {
        return $this->getResourceList(AccountStatus::class, 'account_statuses');
    }

    public function getAccountTypes()
    {
        return $this->getResourceList(AccountType::class, 'account_types');
    }

    public function getAlertLevels()
    {
        return $this->getResourceList(AlertLevel::class, 'alert_levels');
    }
}

2. 通过路由参数动态处理资源

如果允许调整API路由结构,可以用单个方法处理所有资源类型,通过路由参数区分不同模型:

第一步:定义路由

在routes/api.php中添加动态路由:

Route::get('/client/resources/{type}', [ClientController::class, 'getResources']);

第二步:实现控制器方法

use App\Models\AccountStatus;
use App\Models\AccountType;
use App\Models\AlertLevel;
use Illuminate\Http\Request;

class ClientController extends Controller
{
    // 映射资源类型标识到对应的模型和响应键
    private $resourceMap = [
        'account-statuses' => [
            'model' => AccountStatus::class,
            'key' => 'account_statuses'
        ],
        'account-types' => [
            'model' => AccountType::class,
            'key' => 'account_types'
        ],
        'alert-levels' => [
            'model' => AlertLevel::class,
            'key' => 'alert_levels'
        ]
    ];

    public function getResources(Request $request, $type)
    {
        // 校验资源类型合法性
        if (!isset($this->resourceMap[$type])) {
            return response()->json([
                'error' => true,
                'message' => '无效的资源类型'
            ], 400);
        }

        $config = $this->resourceMap[$type];
        try {
            $data = $config['model']::all();
            return response()->json([
                'error' => false,
                'message' => 'OK',
                $config['key'] => $data
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'error' => true,
                'message' => $e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine()
            ], 500宁絮代号        origin Available永反��Letselection七八用户给冒加载控制器方法:
        }
    }
}

调用API时只需传入不同的type参数,比如/client/resources/account-statuses即可获取对应数据。

3. 使用Trait复用跨控制器逻辑

如果多个控制器都有类似的列表查询需求,可以把通用逻辑抽成Trait,实现代码复用:

第一步:创建Trait

// app/Traits/ResourceListTrait.php
namespace App\Traits;

use Illuminate\Http\JsonResponse;

trait ResourceListTrait
{
    /**
     * 获取指定模型的列表并返回统一格式响应
     * @param string $modelClass 模型类全名
     * @param string $responseKey 响应中的数据键名
     * @return JsonResponse
     */
    public function getResourceList($modelClass, $responseKey): JsonResponse
    {
        try {
            $data = $modelClass::all();
            return response()->json([
                'error' => false,
                'message' => 'OK',
                $responseKey => $data
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'error' => true,
                'message' => $e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine()
            ], 500);
        }
    }
}

第二步:在控制器中使用Trait

use App\Models\AccountStatus;
use App\Models\AccountType;
use App\Models\AlertLevel;
use App\Traits\ResourceListTrait;

class ClientController extends Controller
{
    use ResourceListTrait;

    public function getAccountStatuses()
    {
        return $this->getResourceList(AccountStatus::class, 'account_statuses');
    }

    public function getAccountTypes()
    {
        return $this->getResourceList(AccountType::class, 'account_types');
    }

    public function getAlertLevels()
    {
        return $this->getResourceList(AlertLevel::class, 'alert_levels');
    }
}

内容的提问来源于stack exchange,提问作者breekoy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 19:17:02