Полиморфные отношения Laravel с настраиваемой сводной таблицей

у меня есть следующее

    Schema::create('bursary_providers', function (Blueprint $table) {
        $table->increments('id')->unsigned()->index();
        $table->string('bursary_provider',64);
        $table->timestamps();
    });

    Schema::create('bursary_provider_contacts', function (Blueprint $table) {
        $table->increments('id')->unsigned()->index();
        $table->integer('bursary_provider_id')->unsigned()->index();
        $table->foreign('bursary_provider_id')->references('id')->on('bursary_providers')->onDelete('cascade');
        $table->integer('contact_id')->unsigned()->index();
        $table->foreign('contact_id')->references('id')->on('contacts')->onDelete('cascade');
        $table->timestamps();
    });

    Schema::create('contacts', function (Blueprint $table) {
        $table->increments('id')->unsigned()->index();
        $table->string('contact_name', 32);
        $table->timestamps();
    });

1) Да, я знаю, что это не соответствует типичному соглашению, когда хранится «тип». Я делаю это, как указано выше, для ссылочной целостности.

2) Я храню его в сводной таблице с настраиваемым именем, потому что это имеет для меня больше смысла. Требования к сводной таблице Laravels заключаются в том, что она должна быть в алфавитном порядке, но давайте сохраним ее так, поскольку я хочу, чтобы имя было parent_child

Теперь, как мне настроить мою модель? Насколько я понимаю, этот случай будет morphMany (есть и другие родители, кроме bursary_providers — опущены во избежание путаницы). Поэтому я бы использовал в своей модели BursaryProvider следующее:

public function contacts() {
    return $this->morphMany('App\Contact');
}

И следующее в моей модели контактов:

public function bursary_provider () {
    return $this->morphTo();
}

Как изменить приведенное выше, чтобы они правильно подключались с помощью bursary_providers.id / contacts.id и сводной таблицы bursary_provider_contactsbursary_provider_id и contact_id)?

// Редактировать Для ясности, другой «родительский», отличный от bursary_providers (bursary_providers может иметь много контактов; bursary_administrators может иметь много контактов; контакты принадлежат одному):

    Schema::create('bursary_administrators', function (Blueprint $table) {
        $table->increments('id')->unsigned()->index();
        $table->string('bursary_administrator',64);
        $table->timestamps();
    });

    Schema::create('bursary_provider_contacts', function (Blueprint $table) {
        $table->increments('id')->unsigned()->index();
        $table->integer('bursary_administrator_id')->unsigned()->index();
        $table->foreign('bursary_administrator_id')->references('id')->on('bursary_administrators')->onDelete('cascade');
        $table->integer('contact_id')->unsigned()->index();
        $table->foreign('contact_id')->references('id')->on('contacts')->onDelete('cascade');
        $table->timestamps();
    });

person SupaMonkey    schedule 09.08.2018    source источник
comment
Я нигде не вижу отношения морфинга. Все выглядит как отношение многие ко многим: laravel.com/docs/5.6 /eloquent-relationship#many-to-many. С другой стороны, я не думаю, что вам нужно добавлять -›index() к столбцам -›increments().   -  person Adrian Hernandez-Lopez    schedule 09.08.2018
comment
morphMany ? Откуда вы это берете??   -  person Colin Barstow    schedule 09.08.2018
comment
можете ли вы включить других родителей, кроме bursary_providers, чтобы мы могли определить тип отношения, потому что теперь это many-to-many с задействованными только этими таблицами. Кроме того, удалите unsigned()->index() для всех id, потому что это первичный ключ.   -  person gil    schedule 09.08.2018
comment
обновленный вопрос с более подробной информацией в соответствии с запрошенными выше комментариями. С другой стороны, (1) зачем мне удалять неподписанные? мне не нужны отрицательные идентификаторы (2), зачем удалять индекс, если я хочу индексировать идентификатор?   -  person SupaMonkey    schedule 09.08.2018
comment
Мое понимание «многие ко многим» также означает, что многие конкретные контакты могут принадлежать многим bursary_providers. Это не так, один конкретный контакт может принадлежать только одному bursary_provider. У одного bursary_provider может быть много контактов.   -  person SupaMonkey    schedule 09.08.2018


Ответы (1)


Если вы не хотите следовать соглашениям об именах Laravel, я бы настоятельно не советовал этого делать. Главным образом потому, что если вы следуете соглашениям, это работает, а во-вторых, вы просто делаете больше работы для себя!

Итак, что вам нужно сделать, это передать желаемое имя таблицы в качестве второго параметра отношения. Я не могу понять, почему вы используете morphMany, вы должны использовать ownToMany.

Пример

public function contacts() {
    return $this->belongsToMany(App::Contact, 'bursary_provider_contacts');
}

public function bursary_provider () {
    return $this->belongsToMany(Bursary provider::class, 'bursary_provider_contacts');
}

Изменить

Так же, как примечание о типах отношений

Допустим, у вас есть модель продукта, модель заказа и модель счета.

Теперь продукты могут принадлежать заказу, они также могут принадлежать счету.

Это не оправдывает полиморфные отношения, это просто означает, что у вас будут следующие таблицы:

продукты заказы счета order_product invoice_product

Теперь пример полиморфа, Laravel использует тот же самый пример, потому что он распространен.

Скажем, у вас есть модель поста, модель видео и модель комментария.

Теперь модель сообщений может иметь комментарии.

И видео модель могла иметь комментарии.

Таким образом, вместо создания модели PostComment и VideoComment вы можете просто построить модель Comment, и, определив полиморфные отношения, комментарии для обеих моделей будут храниться в связи с желаемой моделью.

Я не хочу быть снисходительным, но серьезно ознакомьтесь с документами Laravel, они очень полезны.

https://laravel.com/docs/5.6/eloquent-relationships#polymorphic-relations
person Colin Barstow    schedule 09.08.2018
comment
обновленный вопрос с более подробной информацией в соответствии с запрошенными выше комментариями - person SupaMonkey; 09.08.2018
comment
Все еще не полиморфные отношения - person Colin Barstow; 09.08.2018
comment
Ясно, что мое понимание взаимосвязей неверно, ваше решение ownToMany похоже помогло. - person SupaMonkey; 09.08.2018
comment
Не волнуйтесь! Я когда-то делал то же самое! - person Colin Barstow; 09.08.2018
comment
На заметку, если не считать таблицы определения отношения; где еще я мог бы создать больше работы для себя (сейчас или в будущем)? - person SupaMonkey; 09.08.2018
comment
Когда вы используете обычные термины именования, например, таблицу продуктов, таблицу заказов, а затем таблицу order_products со столбцами product_id и order_id, laravel мгновенно сопоставляет взаимосвязь. с помощью простого $this-›belongsToMany(Product::class); Когда вы начинаете использовать разные имена, вам нужно сопоставить их вручную, объявив имя таблицы и, в нечетных случаях, столбец. Это может показаться пустяком, но, скажем, вам нужно сделать это с 50 разными отношениями, вы потратите кучу дополнительного рабочего времени. Также существует Laravel, поэтому вам не нужно заниматься всей этой скучной ерундой. - person Colin Barstow; 09.08.2018
comment
Кроме того, его намного проще поддерживать, потому что то, что сейчас может показаться хорошей идеей, может не иметь для вас смысла через несколько месяцев/лет. - person Colin Barstow; 09.08.2018