在Laravel 5.4上的belongsToMany关系中使用Custom Pivot Model

时间:2017-07-04 22:51:55

标签: php laravel pivot

我试图找出如何与自定义中间模型(数据透视表)实现多对多的关系。这是我的模特:

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
        // ??
    }
}

所以,我的问题是如何检索特定区域的横幅?

1 个答案:

答案 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
  }
]