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

Laravel8实现旅游对象点赞评论提交后返回404错误排查

问题定位与修复方案

你看到的是Apache返回的原生404响应,不是Laravel框架抛出的异常,核心原因是请求根本没有进入Laravel的路由解析流程,直接被Web服务器判定为不存在的物理路径。

核心诱因

路由参数type传递的值为App\TouristObject,包含反斜杠\,该字符会被Apache识别为路径分隔符,最终实际请求路径被解析为/like/1/App/TouristObject这类多级路径,和你定义的路由规则完全不匹配,且服务器上不存在对应物理文件,直接返回404。


分步修复方案

1. 修复路由参数特殊字符问题

第一步:给路由添加参数正则约束

修改路由定义,允许type参数包含斜杠类特殊字符:

// routes/web.php
Route::get('/like/{likeable_id}/{type}','FrontendController@like')
    ->name('like')
    ->where('type', '.*');
Route::get('/unlike/{likeable_id}/{type}','FrontendController@unlike')
    ->name('unlike')
    ->where('type', '.*');
Route::post('/addComment/{commentable_id}/{type}','FrontendController@addComment')
    ->name('addComment')
    ->where('type', '.*');

第二步:对类名参数做编码传递

不要直接把带反斜杠的类名拼在URL里,在视图层生成路由时对类名做base64编码,避免破坏URL结构:

  • 点赞/取消点赞链接修改:
@auth
    @if( $touristObject->isLiked() )
    <a href="{{ route('unlike', [
        'likeable_id' => $touristObject->id,
        'type' => base64_encode('App\TouristObject')
    ]) }}" class="btn btn-primary btn-xs top-buffer">Odlub ten obiekt</a>
    @else
    <a href="{{ route('like', [
        'likeable_id' => $touristObject->id,
        'type' => base64_encode('App\TouristObject')
    ]) }}" class="btn btn-primary btn-xs top-buffer">Polub ten obiekt</a>
    @endif
@else
    <p><a href="{{ route('login') }}">Zaloguj się aby polubić obiekt</a></p>
@endauth
  • 评论表单action修改:
<form method="POST" action="{{ route('addComment', [
    'commentable_id' => $touristObject->id, 
    'type' => base64_encode('App\TouristObject')
]) }}" class="form-horizontal">
    @csrf {{-- 必须加CSRF令牌,否则POST请求会报419错误 --}}
    <fieldset>
    <!-- 原有表单内容保持不变 -->

第三步:控制器层解码参数

在控制器中拿到type参数后先做base64解码,再传递给下层逻辑:

// FrontendController.php
public function like($likeable_id, $type, Request $request)
{
    $type = base64_decode($type);
    $this->fR->like($likeable_id, $type, $request);
    return redirect()->back();
}

public function unlike($likeable_id, $type, Request $request)
{
    $type = base64_decode($type);
    $this->fR->unlike($likeable_id, $type, $request);
    return redirect()->back();
}

public function addComment($commentable_id, $type, Request $request)
{
    $type = base64_decode($type);
    $this->fG->addComment($commentable_id, $type, $request); // 原有逻辑漏了调用网关层,直接调仓库会跳过参数校验
    return redirect()->back();
}

2. 确认Apache重写规则生效

如果改完上述内容还是返回Apache原生404,检查两点配置:

  • 站点根目录必须指向Laravel项目的public文件夹,不能指向项目根目录
  • Apache已经开启mod_rewrite模块,且public目录下默认的.htaccess文件没有被删除,允许URL重写生效。
    验证方式:访问Laravel自带的/login路由,如果能正常打开登录页,说明重写规则正常。

现有代码其他隐患修复

  • 修复isLiked方法的游客访问报错问题:游客访问时Auth::user()为null,直接调用会抛出空指针错误,修改模型方法:
// TouristObject.php
public function isLiked()
{
    if (!auth()->check()) {
        return false;
    }
    return $this->users()->where('user_id', auth()->id())->exists();
}
  • 修复评论功能rating字段赋值错误:原有代码把评论内容赋值给了数字类型的rating字段,修改仓库层逻辑:
// FrontendRepository.php
public function addComment($commentable_id, $type, $request)
{
    $commentable = $type::find($commentable_id);
    $comment = new Comment;
    $comment->content = $request->input('content');
    // 原错误写法是把content赋值给rating,这里改为取请求中的rating值,默认0
    $comment->rating = $type == 'App\TouristObject' ? (int)$request->input('rating', 0) : 0;
    $comment->user_id = $request->user()->id;
    return $commentable->comments()->save($comment);
}

优化建议:不要在URL中直接传递完整类名,既存在特殊字符问题,也有安全风险(攻击者可构造参数实例化其他类)。可以在控制器中维护类型映射表,例如$typeMap = ['object' => \App\TouristObject::class],前端只需要传递短标识object,后端从映射表取对应类名,从根源规避特殊字符问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 10:36:43