تحدثنا في مقال سابق عن العلاقة Polymorphic في لارافيل، وكيفية عمل جدول واحد للتعليقات لمجموعة من الجداول، في هذا المقال سوف نتحدث عن علاقة Polymorphic Many.
ما هي العلاقة Polymorphic Many.
لفرض ان لدينا الجداول التالية
Articles
Id
Name
Videos
Id
Name
Products
Id
Name
Tags
Id
Nameولكن لدينا كل ( مقال، فيديو، منتج) يحتوي على مجموعة من التعليقات، وكل تعليق ينتمي لأكثر من ( فيديو، مقال، منتج).
أي أن العلاقة many to many polymorphic.
إنشاء جدول للعلاقة Polymorphic
بما أننا نتعامل مع جدول Tags هنا نحتاج لإنشاء جدول جديد باسم tagables، ولو كنا نتعامل مع جدول videos فإن إسم الجدول الجديد سيكون videoables... وهكذا
public function up()
{
Schema::create('tagables', function (Blueprint $table) {
$table->foreignId('tag_id')->constrained();
$table->morphs('tagable');
$table->timestamps();
});
}توضيح
النوع morphs(tagable) ستقوم بإنشاء حقلين وهما:
- tagable_type: وبه يتم تحديد مسار الموديل التابع له التعليق.
- tagable_id : وبه يتم تحديد id المقال، أو id الفيديو ، أو id المنتج.
تم وضع الإسم tagable في النوع morphs لأن إسم الجدول هو tagables ، ولو كان إسم الجدول videoables فإن إسم النوع morphs يجب أن يكون videoable ، أي أن إسم العلاقة يجب أن يكون singular.

إنشاء العلاقات في علاقة Polymorphic Many
بالطبع نحتاج لبناء العلاقات في الـ Model (Article, Video, Product)، وكذلك بناء العلاقات في الـ Model Tag.
الموديل Tag
في الموديل tag نحتاج لبناء علاقة لجميع الـ model الأخرى (Article, Video, Product)
class Tag extends Model
{
use HasFactory;
protected $fillable = ['tag_id'];
public function articles()
{
return $this->morphedByMany(Article::class,'tagable');
}
public function videos()
{
return $this->morphedByMany(Video::class,'tagable');
}
public function projects()
{
return $this->morphedByMany(Project::class,'tagable');
}
}توضيح
نوع العلاقة يجب أن يكون morphByMany ومن ثم إسم الموديل، ومن ثم tagable لأننا نتعامل مع الجدول tags، فلو كنا نتعامل مع جدول videos فإنها يجب أن تكون videoable.
أما الموديل الأخرى
class Video extends Model
{
use HasFactory;
public function tags()
{
return $this->morphToMany(Tag::class,'tagable');
}
}
class Article extends Model
{
use HasFactory;
public function tags()
{
return $this->morphToMany(Tag::class,'tagable');
}
}
class Product extends Model
{
use HasFactory;
public function tags()
{
return $this->morphToMany(Tag::class,'tagable');
}
}
توضيح
في الموديل ( Product, Video, Article)، كما نرى أن إسم الدالة هي tags في جميع الموديل، نوع العلاقة morphToMany، ومن ثم tagable.
إدخال البيانات في علاقة Polymorphic Many
لفرض أننا لدينا فورم لإدخال المقالات، حيث يمكن كتابة عنوان المقال ، وإختيار مجموعة من الوسوم لهذا المقال
<form method="POST" action="{{ route('articles.store') }}">
@csrf
<input type="text" name="name" class="form-control">
<select name="tag_id[]" multiple class="form-control">
@foreach($tags as $tag)
<option value="{{ $tag->id }}">{{ $tag->tag_name }}</option>
@endforeach
</select>
<button type="submit" class="btn btn-primary">Submit</button>
</form>لإدخال البيانات في Article Controller في الدالة Store
public function store(Request $request)
{
$article= new Article();
$article->name = $request->name;
$article->save();
$article->tags()->attach($request->tag_id);
}
توضيح
- بداية تم حفظ المقال
- إستخدام العلاقة tags ومن ثم إستخدام الدالة attach لحفظ tag_id في جدول tagables، حيث بشكل تلقائي يتم تخزين :
- tag_id : وهو id الـ tag من جدول tags.
- Tagable_type : وبه يتم تخزين مسار الموديل، في حالتنا هذا بما إننا قمنا بإدخال مقال سيتم إدخال App\Models\Article.
- Tagable_id : وبه يتم تخزين id المقال.
ممكن الإطلاع على الصوره بالأعلى.
عرض البيانات في علاقة Polymorphic Many
لفرض إننا نريد عرض مقال معين مع الوسوم التابعة له
public function show($id)
{
$article=Article::with('tags')->findOrFail($id);
return view('article_details', compact('article'));
}كما نلاحظ أن كل ما علينا هو إستخدام with مع إسم الدالة التي بها العلاقة وهي tags.