Laravel Eloquent多对多关联及翻译问题求助
嘿,我来帮你搞定这个带翻译的多对多关联问题!首先咱们先把现有模型里的小问题修正掉,然后再实现你要的功能。
第一步:修正模型里的关联错误
先看几个容易踩坑的地方:
- Accessori模型里的
accessoriProducts方法,关联的模型应该是App\Product(单数),不是App\Products,改完后是这样:public function accessoriProducts() { return $this->belongsToMany('App\Product', 'accessori_products', 'accessori_id', 'products_id'); } - ProductAccessori模型的关联写法不对,其实如果你的中间表
accessori_products只有关联ID(没有额外字段),甚至不需要这个模型——Laravel的多对多关联会自动处理中间表。如果一定要保留这个模型,正确的关联应该是:class ProductAccessori extends Model { protected $table = 'accessori_products'; // 关联产品 public function product() { return $this->belongsTo('App\Product', 'products_id'); } // 关联配件 public function accessori() { return $this->belongsTo('App\Accessori', 'accessori_id'); } }
第二步:获取产品+关联配件+对应翻译
核心思路是用**预加载(Eager Loading)**嵌套关联,一次性把所有需要的数据查出来,避免N+1查询问题。
方案1:保留现有hasMany关联(当前语言)
在控制器里,获取产品的时候同时预加载产品翻译、配件,以及配件的当前语言翻译:
use App\Product; // 获取所有产品 $products = Product::with('productsLang', 'accessori.accessoriLang')->get(); // 或者获取单个指定产品 $product = Product::with('productsLang', 'accessori.accessoriLang')->find($yourProductId);
然后在视图里遍历使用(因为hasMany返回的是集合,所以用first()取第一条):
@foreach($products as $product) <div class="product"> <h2>{{ $product->productsLang->first()->product_name }}</h2> <h3>关联配件:</h3> <ul> @foreach($product->accessori as $accessory) <li>{{ $accessory->accessoriLang->first()->accessori_name }}</li> @endforeach </ul> </div> @endforeach
方案2:优化关联为hasOne(更高效)
因为对于当前语言,每个产品/配件只会有一条翻译,所以把hasMany改成hasOne会更高效,不用每次都调用first():
修改Product模型的productsLang方法:
public function productsLang() { return $this->hasOne('App\ProductLng', 'products_id')->where('lang','=',App::getLocale()); }
修改Accessori模型的accessoriLang方法:
public function accessoriLang() { return $this->hasOne('App\AccessoriLng')->where('lang','=',App::getLocale()); }
然后控制器里的预加载代码不变,视图里可以直接调用:
@foreach($products as $product) <div class="product"> <h2>{{ $product->productsLang->product_name }}</h2> <h3>关联配件:</h3> <ul> @foreach($product->accessori as $accessory) <li>{{ $accessory->accessoriLang->accessori_name }}</li> @endforeach </ul> </div> @endforeach
第三步:如果需要获取所有语言的翻译
如果要拿到某个产品/配件的所有语言版本,直接用你定义的productsLangAll和accessoriLangAll关联就行,比如:
$product = Product::with('productsLangAll', 'accessori.accessoriLangAll')->find($yourProductId);
这样就能拿到每个配件的所有语言翻译,遍历的时候可以按语言筛选。
内容的提问来源于stack exchange,提问作者DaFois
相关产品推荐
相关产品推荐

