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

for*_*edw 4 many-to-many pivot-table laravel eloquent laravel-5

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

我有两张桌子,companies还有respondents

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

其他时候,受访者可以评价一个或更多的公司。一家公司可以由一名或多名受访者评分

受访者可以选择评价一家公司。(确实,受访者必须选择所有对其进行评分的公司,但他们并未对他们选择的所有公司进行评分)。

更复杂的是,受访者只是一家公司的员工,而且还被一家或多家公司提名参加评选和评级。

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

//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
Run Code Online (Sandbox Code Playgroud)

我猜最后一个是简单的一对多,所以我可以employer_idrespondents表中放一个名为 FK 的自定义。

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

for*_*edw 5

好的,这就是我如何处理这个问题的。

自定义数据透视表

在数据透视中,我添加了一个名为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']);
    });
Run Code Online (Sandbox Code Playgroud)

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

带枢轴

在我这样做之前,我需要告诉 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');
    }
Run Code Online (Sandbox Code Playgroud)

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

储存:

$respondent->companies()->attach($companies_selected, ['type'=> 'selected']);
Run Code Online (Sandbox Code Playgroud)

哪里$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();
Run Code Online (Sandbox Code Playgroud)

我可以简单地替代selectedratednominated或其他任何东西,我喜欢定义不同的类型,可以在两个表之间存在的关系。

我希望这对其他人有所帮助,或者我会获得有关执行此操作的更好方法的反馈。