Метод morphedByMany
Метод morphedByMany используется в Eloquent для определения обратной стороны полиморфной связи "многие ко многим". Первым параметром передаётся имя связанной модели, вторым - имя, используемое для формирования названий столбцов и таблицы, третьим - имя таблицы связей, четвёртым - имя внешнего ключа текущей модели, пятым - имя внешнего ключа связанной модели. В отличие от метода morphToMany, который определяет прямую связь, morphedByMany используется в модели, которая может быть связана с несколькими типами моделей через одну промежуточную таблицу.
Основное отличие morphedByMany от morphToMany заключается в том, что первый метод применяется в модели, которая является "полиморфной" стороной связи. Например, если у вас есть модель Tag, которая может принадлежать моделям Post и Video, то в модели Tag для получения связанных постов вы используете morphedByMany.
Синтаксис
<?php
Model::morphedByMany($related, $name, $table = null, $foreignPivotKey = null, $relatedPivotKey = null, $parentKey = null, $relatedKey = null);
?>
Параметры метода:
-
$related- имя связанной модели -
$name- имя, используемое для формирования названий столбцов и таблицы -
$table- имя промежуточной таблицы (необязательный параметр) -
$foreignPivotKey- имя внешнего ключа текущей модели (необязательный параметр) -
$relatedPivotKey- имя внешнего ключа связанной модели (необязательный параметр) -
$parentKey- имя локального ключа текущей модели (необязательный параметр) -
$relatedKey- имя локального ключа связанной модели (необязательный параметр)
Пример
Рассмотрим классический пример с тегами. Создадим модель Tag, которая может быть связана с моделями Post и Video:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Tag extends Model
{
public function posts()
{
return $this->morphedByMany(Post::class, 'taggable');
}
public function videos()
{
return $this->morphedByMany(Video::class, 'taggable');
}
}
?>
Теперь определим модель Post с прямой связью:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Post extends Model
{
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable');
}
}
?>
Аналогично для модели Video:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Video extends Model
{
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable');
}
}
?>
Теперь создадим миграцию для промежуточной таблицы:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
public function up()
{
Schema::create('taggables', function (Blueprint $table) {
$table->id();
$table->morphs('taggable');
$table->foreignId('tag_id')->constrained()->cascadeOnDelete();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('taggables');
}
};
?>
Пример
Теперь получим все посты, которые имеют определённый тег:
<?php
namespace AppHttpControllers;
use AppModelsTag;
class TagController extends Controller
{
public function showPosts($tagId)
{
$tag = Tag::find($tagId);
$posts = $tag->posts()->get();
foreach ($posts as $post) {
echo $post->title;
}
}
}
?>
Результат выполнения кода:
["First post", "Second post", "Third post"]
Пример
Получим все видео, которые имеют определённый тег:
<?php
namespace AppHttpControllers;
use AppModelsTag;
class TagController extends Controller
{
public function showVideos($tagId)
{
$tag = Tag::find($tagId);
$videos = $tag->videos()->get();
foreach ($videos as $video) {
echo $video->title;
}
}
}
?>
Результат выполнения кода:
["First video", "Second video"]
Пример
Добавим новый тег к посту:
<?php
namespace AppHttpControllers;
use AppModelsPost;
use AppModelsTag;
class PostController extends Controller
{
public function attachTag($postId, $tagId)
{
$post = Post::find($postId);
$post->tags()->attach($tagId);
echo "Tag attached successfully";
}
}
?>
Результат выполнения кода:
"Tag attached successfully"
Смотрите также
-
метод
morphToMany,
который определяет прямую полиморфную связь многие ко многим -
метод
morphTo,
который определяет обратную полиморфную связь -
метод
morphMany,
который определяет полиморфную связь один ко многим -
метод
belongsToMany,
который определяет обычную связь многие ко многим