Я не уверен, что именно вы пытаетесь сделать, но таблица с двумя полиморфными отношениями не имеет смысла. Таблица, которая включает полиморфное отношение, является сводной таблицей. Хотя я получаю, что вам нужны уникальные описания для каждого тега и типа связи, сводная таблица должна иметь только два столбца внешнего ключа, один из которых относится к таблице.
Есть еще один способ, который заключается в использовании полиморфных отношений в качестве ограничения на сводную таблицу. Для начала с сводной таблицей в полиморфных отношениях следует переименовать ее в «taggables». Вам не нужны таблица «email_tag» и «document_tag», вы можете использовать таблицу с именем «tags». Чтобы получить уникальное описание для каждого тега, вы можете добавить описание в таблицу «tabblables».
Файл миграции выглядит следующим образом ....
public function up()
{
Schema::create('taggables', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('tag_id');
$table->unsignedInteger('taggable_id');
$table->string('taggable_type');
$table->string('description');
$table->timestamps();
});
Schema::create('tags', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Schema::create('documents', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Schema::create('emails', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
Вот, что вам нужно сделать в моделях электронной почты и документов.
class Email extends Model
{
/**
* Get all of the tags.
*/
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable')->withPivot('description');
}
}
class Document extends Model
{
/**
* Get all of the tag descriptions.
*/
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable')->withPivot('description');
}
}
Функция «withPivot» возвращает значение столбца, указанного в запросе.
Вот что вам нужно сделать в вашей модели тегов.
class Tag extends Model
{
/**
* Get all of the tag descriptions.
*/
public function documents()
{
return $this->morphByMany(Document::class, 'taggable');
}
/**
* Get all of the tag descriptions.
*/
public function emails()
{
return $this->morphByMany(Email::class, 'taggable');
}
}
Вам не нужна табличная модель Taggables.
Вот что происходит. Когда вы повозитесь ...
$email = App\Email::find(1)->tags;
Этот запрос будет выполнен ...
select `tags`.*,
`taggables`.`taggable_id` as `pivot_taggable_id`,
`taggables`.`tag_id` as `pivot_tag_id`,
`taggables`.`taggable_type` as `pivot_taggable_type`,
`taggables`.`description` as `pivot_description`
from `tags`
inner join `taggables` on `tags`.`id` = `taggables`.`tag_id`
where `taggables`.`taggable_id` = 1
and `taggables`.`taggable_type` = 'App\Email'
То, что вы видите, это ограничение полиморфных отношений, может запросить уникальное описание. Подводя итог, вы не можете поместить более двух отношений внешнего ключа в сводную таблицу, но вы можете добавить ограничение в вашу сводную таблицу.
Я думаю, что добавить этот файл AppServiceProvider.php выглядит чище ...
public function boot()
{
Relation::morphMap([
'email' => Email::class,
'document' => Document::class
]);
}
https://laravel.com/docs/5.8/eloquent-relationships#polymorphic-relationships
Это позволит вам сохранить значение «email» или «document» в качестве типа тега.
Для публикации в таблицах я думаю, что это выглядит самым чистым ...
$tag = Tag::firstOrNew(["name"=>"#tag"]);
$tag->name = "#tag";
$document = new Document();
$document->name = "new doc";
$document->save();
$document->tags()->save($tag,["description"=>"some description"]);
Вы, конечно, можете использовать attach (). Save () использует метод attach (), как показано здесь ...
https://github.com/laravel/framework/blob/5.8/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php#L871
Надеюсь, это поможет.