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

Laravel路由替换URL斜杠为连字符时出现空值读取错误求助

问题根源分析

你遇到的错误核心原因是路由参数的正则约束无法区分brand_slug和slug的边界:
修改后的路由/mobiles/{brand_slug}-{slug}中,两个参数的正则都允许-字符,导致Laravel无法准确分割URL中的参数。比如lenovo-tab-m9会被错误解析为brand_slug=lenovo-tab、slug=m9,而数据库中不存在slug为lenovo-tab的品牌,最终导致$brand为空,触发Attempt to read property "id" on null错误。


解决方案

根据你的业务场景,提供两种可行方案:

方案一:修改路由正则约束(适用于品牌slug不含连字符)

如果你的品牌slug本身不会包含-,直接调整正则规则,限制brand_slug仅匹配字母、数字和下划线:

Route::get('/mobiles/{brand_slug}-{slug}', 'Frontend\DevicesController@device')
    ->name('device')
    ->where([
        'brand_slug' => '[a-z0-9_]+', // 移除-,避免匹配包含连字符的内容
        'slug' => '[a-z0-9_-]+'
    ]);

此时Laravel会自动将第一个-前的内容作为brand_slug,后面的作为slug,比如lenovo-tab-m9会被正确解析为brand_slug=lenovo、slug=tab-m9。

方案二:单一参数拆分匹配(通用方案,支持品牌slug含连字符)

如果品牌slug可能包含-(比如huawei-mate),推荐改用单一参数,在控制器中主动匹配品牌:

1. 修改路由

Route::get('/mobiles/{combined_slug}', 'Frontend\DevicesController@device')
    ->name('device')
    ->where('combined_slug', '[a-z0-9_-]+');

2. 调整控制器逻辑

public function device(Request $request)
{
    $combinedSlug = $request->combined_slug;
    // 获取所有活跃品牌的slug,按长度降序排序(优先匹配长slug)
    $brandSlugs = DB::table('brands')->where('active', 1)->pluck('slug')->toArray();
    usort($brandSlugs, fn($a, $b) => strlen($b) - strlen($a));

    $brand = null;
    $deviceSlug = '';
    // 遍历匹配品牌slug前缀
    foreach ($brandSlugs as $slug) {
        if (str_starts_with($combinedSlug, $slug . '-')) {
            $brand = DB::table('brands')->where('slug', $slug)->where('active', 1)->first();
            $deviceSlug = substr($combinedSlug, strlen($slug) + 1);
            break;
        }
    }

    // 未匹配到品牌直接返回404
    if (!$brand) abort(404);

    $device = DB::table('devices')
        ->where('status', 'active')
        ->where('slug', $deviceSlug)
        ->where('brand_id', $brand->id)
        ->first();

    if (!$device) abort(404);
    return view('frontend/'.$this->config->template.'/device-specs', ['device' => $device, 'brand' => $brand]);
}

3. 更新Blade链接生成

<div>
  <a title="{{ $device->brand_title.' '.$device->model }}" href="{{ route('device', ['combined_slug' => $device->brand_slug . '-' . $device->slug]) }}" class="image">
    <h3>{{ $device->brand_title.' '.$device->model }}</h3>
  </a>
</div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 18:12:37