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

Laravel中如何通过API请求自动识别多态关联模型并保存Like记录

解决Laravel多态点赞的无分支实现方案

我来给你几个Laravel原生的简洁实现思路,完全不用写一堆if/switch分支,既符合框架设计风格,又能让代码保持干净。

方案一:多态路由 + 路由模型绑定(推荐,RESTful风格)

这是最符合Laravel设计哲学的方案,利用框架自带的路由模型绑定能力,直接让路由自动识别并注入对应的模型实例。

步骤1:定义多态路由

把原来的单一端点改成多态路由,这样不同模型的点赞请求通过不同的URL路径区分:

// routes/api.php
Route::post('/{likeable}/likes', [LikeController::class, 'store']);

访问时的URL示例:

  • 给Video点赞:POST /api/videos/1/likes
  • 给Post点赞:POST /api/posts/2/likes

步骤2:修改控制器方法

直接在方法参数中注入Model类型的变量,Laravel会自动根据URL解析出对应的Video或Post实例:

use Illuminate\Database\Eloquent\Model;
use App\Models\Video;
use App\Models\Post;

public function store(StoreLikeRequest $request, Model $likeable)
{
    // 安全校验:只允许指定的模型类型(避免恶意请求)
    abort_unless(in_array(get_class($likeable), [Video::class, Post::class]), 403, 'Invalid model type');

    // 调用通用的点赞处理Action,无需区分模型
    $result = (new StoreLikeAction($likeable, $request))->handle();
    
    return $result;
}

步骤3:简化请求验证

此时StoreLikeRequest只需要验证点赞相关的业务字段(比如用户身份),完全不用处理模型类型判断:

public function rules()
{
    return [
        // 示例:如果是登录用户点赞,可通过auth()获取,无需传参;如果需要其他字段,在这里验证
        // 'some_field' => 'required|string',
    ];
}

方案二:单一端点 + 请求类模型解析(兼容原有端点)

如果你不想修改现有路由,想保留/api/like/store这种单一端点,可以在请求类里封装模型解析逻辑,用Laravel 8+支持的match表达式替代if/switch,代码依然简洁。

步骤1:更新请求类规则和模型解析方法

在StoreLikeRequest里添加type和id的验证,并新增一个自定义方法获取关联模型:

use App\Models\Video;
use App\Models\Post;

public function rules()
{
    return [
        'type' => 'required|string|in:video,post', // 限制允许的模型类型
        'id' => 'required|integer|exists:'.$this->input('type').'s,id', // 验证ID存在对应表中
        // 其他业务字段验证...
    ];
}

// 自定义方法:返回解析后的模型实例
public function getLikeableModel()
{
    $modelClass = match($this->input('type')) {
        'video' => Video::class,
        'post' => Post::class,
    };

    return $modelClass::findOrFail($this->input('id'));
}

步骤2:修改控制器方法

直接调用请求类的自定义方法获取模型,剩下的逻辑完全通用:

public function store(StoreLikeRequest $request)
{
    $likeable = $request->getLikeableModel();
    $result = (new StoreLikeAction($likeable, $request))->handle();
    
    return $result;
}

通用点赞Action的优化

不管用哪种方案,都可以把点赞逻辑封装成通用的Action,利用多态关联自动处理模型类型存储:

// StoreLikeAction.php
public function __construct(protected Model $likeable, protected StoreLikeRequest $request) {}

public function handle()
{
    $userId = auth()->id(); // 假设是登录用户点赞

    // 避免重复点赞
    if ($this->likeable->likes()->where('user_id', $userId)->exists()) {
        return response()->json(['message' => '您已经点过赞了'], 409);
    }

    // 多态关联会自动填充likeable_type和likeable_id字段
    $like = $this->likeable->likes()->create([
        'user_id' => $userId,
        // 其他点赞相关字段...
    ]);

    return response()->json($like, 201);
}

这样整个流程下来,完全看不到if/switch分支,代码既简洁又符合Laravel的设计风格,扩展性也很强——以后如果要给其他模型加点赞功能,只需要在路由允许的模型列表里添加对应类,或者在请求的type规则里新增选项即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 04:52:42