Laravel中如何翻译动态seo_url?解决getTranslatedAttribute报错问题
解决Laravel动态路由下getTranslatedAttribute调用报错及URL翻译问题
问题概述
在Laravel项目中配置动态路由后,尝试在Blade模板中使用getTranslatedAttribute方法翻译路由对应的seo_url时,出现错误提示:Call to a member function getTranslatedAttribute() on null,需要实现动态URL的翻译功能。
错误原因分析
- 空对象调用方法:
$solution_details为null,即App\Solution::where('seo_url', $seo_url)->first()未查询到对应记录,直接调用getTranslatedAttribute必然报错。 - 查询逻辑错误:
seo_url是多语言可翻译字段,直接用原始$seo_url匹配数据库中的字段,无法正确匹配对应语言的翻译值。 - 路由硬编码语言前缀:路由中硬编码
/en/,不利于多语言扩展,也容易导致语言设置与查询逻辑脱节。
解决方案
1. 优化路由与查询逻辑
改用本地化路由分组,通过中间件统一设置语言,并使用Voyager提供的whereTranslation方法查询对应语言的seo_url:
// routes/web.php Route::group(['prefix' => '{locale}', 'middleware' => 'setlocale'], function () { Route::get('/solutions/{seo_url}', function ($locale, $seo_url) { // 根据当前语言查询对应seo_url的解决方案 $solution_details = App\Solution::whereTranslation('seo_url', $seo_url, $locale)->firstOrFail(); // 预加载所需数据(可根据实际需求优化,比如使用缓存) $themes = App\Theme::all(); $services = App\Service::all(); $referances = App\Referance::all(); $blogs = App\Blog::all(); $solutions = App\Solution::all(); $announcements = App\Announcement::all(); $news = App\News::all(); $subsolutions = App\Subsolution::all(); $pages = TCG\Voyager\Models\Page::all(); // 根据语言加载对应视图 return view("tema.parallax.{$locale}.solution_detail", compact( 'services','solution_details','themes','pages', 'referances' , 'blogs' , 'solutions', 'subsolutions' , 'news', 'announcements' )); }); });
创建SetLocale中间件统一处理语言设置:
// app/Http/Middleware/SetLocale.php <?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\App; class SetLocale { public function handle($request, Closure $next) { $locale = $request->route('locale'); // 限制支持的语言列表,避免非法语言传入 if (in_array($locale, ['en', 'tr'])) { App::setLocale($locale); } return $next($request); } }
记得在app/Http/Kernel.php的$routeMiddleware中注册中间件:
protected $routeMiddleware = [ // 其他中间件... 'setlocale' => \App\Http\Middleware\SetLocale::class, ];
2. 优化Blade模板,增加空值判断
在模板中先判断$solution_details是否存在,再执行后续逻辑,避免空对象调用方法:
<div class="container ms-content"> <div class="row justify-content-between"> <div class="row blog-sidebar grid-content col-lg-12"> <div class="grid-sizer col-12"></div> {{-- 先校验solution_details是否存在 --}} @if($solution_details) @if ("{{ request()->locale() }}/solutions/" . $solution_details->getTranslatedAttribute('seo_url', request()->locale(), 'fallbackLocale') == Request::path()) <article class="grid-item col-12 pb-lg-5"> <div class="work-card card--is-link"> <figure class="card__img media-wrapper media-wrapper--21:9"> <img src="/storage/{{ $solution_details->resim }}" alt="{!! $solution_details->getTranslatedAttribute('baslik', request()->locale(), 'fallbackLocale') !!}"> <div class="glow-wrap"><i class="glow"></i></div> </figure> <br> <div class="card__content"> <a class="card__title"> <h4>{!! $solution_details->getTranslatedAttribute('baslik', request()->locale(), 'fallbackLocale') !!}</h4> </a> <p class="text-sm post-excerpt">{!! $solution_details->getTranslatedAttribute('aciklama', request()->locale(), 'fallbackLocale') !!}</p> <div class="post-info__footer"><span class="post-info__divider"></span></div> </div> </div> </article> @endif @else {{-- 无匹配记录时的提示 --}} <div class="col-12 text-center py-5"> <h5>未找到对应的解决方案</h5> </div> @endif </div> </div> </div>
关键优化点
- 使用
firstOrFail():查询不到记录时直接返回404页面,避免后续空值问题。 whereTranslation方法:正确匹配对应语言的翻译字段,解决动态URL的多语言查询问题。- 本地化路由分组:统一管理多语言路由,便于扩展新语言。
- 空值判断:模板中先校验对象是否存在,再调用方法,彻底避免空对象报错。
内容的提问来源于stack exchange,提问作者Emre Kd
相关产品推荐
相关产品推荐

