我试图找出如何与自定义中间模型(数据透视表)实现多对多的关系。这是我的模特:
banners
- id
- title
- description
banner_regions (Pivot)
- id
- region_id
- banner_id
- active
regions
- id
- name
- slug
Eloquent Models代码:
class Banner extends Model
{
/**
* Get all of the regions for the banner.
*/
public function regions()
{
return $this->belongsToMany('App\Region', 'banner_regions')
->withPivot('active')
->using(BannerRegion::class);
}
}
class BannerRegion extends Model
{
}
class Region extends Model
{
/**
* Get all of the banners for the region.
*/
public function banners()
{
return $this->belongsToMany('App\Banner', 'banner_regions')
->withPivot('active')
->using(BannerRegion::class);
}
}
横幅控制器代码:
class BannerController extends Controller
{
protected $model;
public function __construct(Banner $model)
{
$this->model = $model;
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
$region = $request->region; // region model instance
// ??
}
}
所以,我的问题是如何检索特定区域的横幅?
答案 0 :(得分:2)
<强>解强>
我已经更改了我的代码,现在它按预期工作了。
我将BannerRegion数据透视模型更改为Pivot
而不是Model
:
<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class BannerRegion extends Pivot
{
// It is just for casting int values into boolean values.
// Useful for JSON responses.
protected $casts = [
'active' => 'boolean',
'for_customers' => 'boolean',
];
}
横幅模型。没有什么可以在这里添加,但我做了一些更改,以改善JSON响应,如$appends
。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Banner extends Model
{
protected $hidden = ['id', 'regions'];
// Add data from the pivot model
protected $appends = ['for_customers'];
public function getForCustomersAttribute()
{
// Get the attribute 'for_customers' from the pivot model
return $this->regions
->keyBy('pivot.banner_id')
->get($this->id)
->pivot
->for_customers;
}
/**
* Get all of the regions for the banner.
*
*/
public function regions()
{
return $this->belongsToMany('App\Region', 'banner_regions')
->withPivot('for_customers', 'active')
->using('App\BannerRegion');
}
/**
* Scope a query to only include active banners for a specific region.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param App\Region $region
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeFindbyRegionAndActive($query, Region $region)
{
return $query->whereHas('regions', function($query) use ($region) {
return $query->whereRegionId($region->id)->whereActive(true);
});
}
}
在我的Banner控制器中,我刚刚添加了:
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Region $region)
{
return $this->model->findbyRegionAndActive($region)->get();
}
区域参数由依赖注入解决(laravel.com/docs/5.4/routing#route-model-binding)。
最后,我的路线:
Route::group(['prefix' => '/regions/{region}'], function()
{
// Banners
Route::resource('banners', 'BannerController', ['only' => 'index']);
});
终点:
/regions/my-region/banners
JSON回复:
[
{
"title": "a title...",
"description": "a descritpion...",
"link": "http://localhost",
"for_customers": true
}
]