Laravel具有多个自定义数据透视表的多对多关系?

时间:2018-12-10 10:52:43

标签: laravel laravel-5 eloquent many-to-many pivot-table

我希望我不是在问一个已经回答的问题,但是使用我能想到的所有搜索词我都无法解决此问题:

我有两个表companiesrespondents

有时候,受访者可以选择一个或多个公司。一个或多个受访者可以选择一家公司。

其他时候,受访者可以评价一个或多个公司。一家或多名受访者可以对公司进行评级

受访者有可能同时选择评价一家公司。 (实际上,所有被受访者评价他们必须选择的公司,但他们并未对他们选择的所有公司进行评价。

更复杂的是,被访者仅是一家公司的雇员,并且由一个或多个公司提名进行选择和评级。

我的思路是拥有多个自定义枢纽:

//relationship between 'companies' and 'respondents' to show who they selected 
selected_companies 

//relationship between 'companies' and 'respondents' to show who they rated 
rated_companies 

//relationship between 'companies' and 'respondents' to show which companies a respondent was nominated by 
nominating_companies

//relationship between 'companies' and 'respondents' to show who a respondent is employed by
employment

我想最后一个是简单的一对多,所以我可以在employer_id表中放入一个名为respondents的自定义FK。

除此之外,我对如何实现这一点非常困惑。我知道自定义中间枢轴模型是一回事,但我也想不出如何实现它。

1 个答案:

答案 0 :(得分:1)

好的,这就是我的处理方式。

自定义数据透视表

在数据透视图中,我添加了一个名为type的列。这就是我的company_respondent数据透视表迁移现在的样子:

    Schema::create('company_respondent', function (Blueprint $table) {
        $table->unsignedInteger('company_id');
        $table->unsignedInteger('respondent_id');
        $table->string('type');

        $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
        $table->foreign('respondent_id')->references('id')->on('respondents')->onDelete('cascade');
        $table->primary(['company_id','respondent_id','type']);
    });

请注意,对于主键,我使用了所有三列。这将允许我声明同一对公司-受访者对之间的不同类型的关系,例如当受访者选择了一家公司时,我可以存储selected,当他们对一家公司进行评级时,可以在rated列中存储type

withPivot

在执行此操作之前,我需要告诉Laravel在定义关系时期望CompanyRespondent模型中使用withPivot()的新列。我需要在关系的两边都这样做:

//Respondent.php

    use App\Company;

    public function companies() 
    {
        return $this->belongsToMany(Company::class)->withPivot('type');
    }


//Company.php

    use App\Respondent;

    public function respondents() 
    {
        return $this->belongsToMany(Respondent::class)->withPivot('type');
    }

完成后,现在可以在保存关系时将其存储到该列中,并使用它进行过滤。

存储:

$respondent->companies()->attach($companies_selected, ['type'=> 'selected']);

$companies_selected是单个ID或ID数组。

过滤:

//returns an array of company names that a respondent with an id of `2` has selected.

$company_names = Respondent::find(2)
                    ->companies()
                    ->wherePivot('type','selected')
                    ->pluck('name')->toArray();

我可以简单地用selectedratednominated或其他我喜欢的东西来定义两个表之间可能存在的不同类型的关系。

我希望这对其他人有帮助,或者我希望获得更好的反馈方法。