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

Laravel访问pay路由触发vodplay组件空属性读取错误求助

Laravel路由匹配错误导致无关组件触发异常

问题

访问与vodplay组件无关的pay路由时,触发组件中的「Attempt to read property 'price' on null」错误,项目其他路由运行正常。已尝试清除缓存、新建路由及控制器,问题仍存在。

原因分析

路由匹配顺序错误是核心问题:
在web.php中,通配符路由Route::get('/{id}', [videoController::class, 'play'])->name('play')定义在/pay路由之前。Laravel路由采用从上到下匹配的规则,当访问/pay时,Laravel会将pay当作{id}的参数值,匹配到videoController@play方法。而该方法中大概率调用了vodplay组件,传入的id为字符串pay,数据库中不存在对应ID的Video记录,导致video::where('id',$this->id)->first()返回null,直接访问$price->price就触发了属性读取错误。

解决方案

1. 调整路由顺序

将具体路由(如/pay)放在通配符路由(/{id})之前,确保Laravel优先匹配明确的路由:
修改后的web.php代码:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\homeController;
use App\Http\Controllers\videoController;
use App\Http\Controllers\loginController;
use App\Http\Controllers\payController;

Route::get('/', [homeController::class, 'index'])->name('home');

Route::get('/login', [loginController::class, 'index'])->name('login');

Route::post('/verify', [loginController::class, 'verify'])->name('verify');

Route::post('/ver', [loginController::class, 'doverify'])->name('doverify');

Route::get('/pay', [payController::class, 'index'])->name('pay');

// 通配符路由放到最后
Route::get('/{id}', [videoController::class, 'play'])->name('play');

2. 组件代码增加空值防护

即使路由问题解决,也建议在vodplay组件中增加空值判断,避免因无效ID导致报错:
修改后的组件render方法:

public function render(): View|Closure|string
{
    $video = Video::where('id', $this->id)->first();
    
    // 若视频不存在,直接返回错误视图或提示
    if (!$video) {
        return view('components.video-not-found'); // 可自定义该视图
    }

    $price = $video->price;
    $videodata = $video;
    
    if ($price == '0' || is_null($price)) {
        return view('components.vodplay')->with('videodata', $videodata);
    } else {
        return Payment::purchase(
            (new Invoice)->amount($price), 
            function($driver, $transactionId) {
                // 存储transactionId到数据库
            }
        )->pay()->render();
    }
}

3. 可选:限制通配符路由的参数类型

为/{id}路由添加参数类型约束(如仅匹配数字ID),进一步避免非ID字符串被匹配:

Route::get('/{id}', [videoController::class, 'play'])->name('play')->where('id', '[0-9]+');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 12:18:09