Отношение многие ко многим Laravel с несколькими настраиваемыми сводными таблицами? - PullRequest
0 голосов
/ 10 декабря 2018

Надеюсь, я не задаю вопрос, на который уже дан ответ, но, используя все условия поиска, которые я могу придумать, я не могу найти решение этой проблемы:

У меня есть две таблицы, 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

Я думаю, последний из них является простым для многих, поэтому я могу просто поставить пользовательский с именем FK employer_id в таблице respondents.

Кроме этого, я довольно застрял в том, как это реализовать.Я знаю, что пользовательские модели промежуточных опорных точек - вещь, но я также не могу понять, как это реализовать.

1 Ответ

0 голосов
/ 10 декабря 2018

ОК, вот как я справился с этим.

Настраиваемая сводная таблица

В сводную таблицу я добавил столбец с именем 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 в typecolumn.

withPivot

Прежде чем я смогу это сделать, я должен сказать Laravel ожидать этого нового столбца в моделях Company и Respondent, использующих 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 - это либо один идентификатор, либо массив идентификаторов.

Фильтрация:

//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();

Я могу просто заменить selected, rated, nominated или что-либо еще, что мне нравится, для определения различных типов отношений, которые могут существовать между двумя таблицами.

Я надеюсь, что это поможет кому-то еще, или я получаю отзыв о лучшем способе сделать это.

...