تحدثنا في مقال سابق عن العلاقة Polymorphic في لارافيل، وكيفية عمل جدول واحد للتعليقات لمجموعة من الجداول، في هذا المقال سوف نتحدث عن علاقة Polymorphic Many.
لفرض ان لدينا الجداول التالية
Articles
Id
Name
Videos
Id
Name
Products
Id
Name
Tags
Id
Name
ولكن لدينا كل ( مقال، فيديو، منتج) يحتوي على مجموعة من التعليقات، وكل تعليق ينتمي لأكثر من ( فيديو، مقال، منتج).
أي أن العلاقة many to many 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 في النوع morphs لأن إسم الجدول هو tagables ، ولو كان إسم الجدول videoables فإن إسم النوع morphs يجب أن يكون videoable ، أي أن إسم العلاقة يجب أن يكون singular.
بالطبع نحتاج لبناء العلاقات في الـ 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.
لفرض أننا لدينا فورم لإدخال المقالات، حيث يمكن كتابة عنوان المقال ، وإختيار مجموعة من الوسوم لهذا المقال
<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); }
توضيح
ممكن الإطلاع على الصوره بالأعلى.
لفرض إننا نريد عرض مقال معين مع الوسوم التابعة له
public function show($id) { $article=Article::with('tags')->findOrFail($id); return view('article_details', compact('article')); }
كما نلاحظ أن كل ما علينا هو إستخدام with مع إسم الدالة التي بها العلاقة وهي tags.