Polymorphic در Laravel؛ راهنمای کامل روابط چندشکلی

تاریخ انتشار: 2026/05/27 05:19 بازدید: 18 نویسنده: Admin

Polymorphic در Laravel یکی از قابلیت‌های قدرتمند Eloquent برای طراحی رابطه‌های انعطاف‌پذیر بین مدل‌هاست. با روابط چندشکلی یا Polymorphic Relationships می‌توان یک مدل را به چند نوع مدل مختلف متصل کرد؛ برای مثال یک جدول comments می‌تواند هم برای مقاله‌ها، هم محصولات، هم ویدئوها و هم تیکت‌ها کامنت نگه دارد. در این مقاله، به‌صورت کامل و فنی با مفهوم Polymorphic در Laravel، انواع روابط morphOne، morphMany، morphTo، morphToMany، morphedByMany، طراحی Migration، مثال‌های واقعی، Performance، Eager Loading، Morph Map، خطاهای رایج و بهترین روش‌های استفاده در پروژه‌های شرکتی آشنا می‌شویم.

1.0x

برای شنیدن متن، روی «پخش صوت مقاله» بزنید.

مقدمه

در توسعه نرم‌افزارهای واقعی، مدل‌های دیتابیس همیشه رابطه‌های ساده و مستقیم ندارند. گاهی یک موجودیت باید بتواند به چند نوع موجودیت مختلف متصل شود. برای مثال، فرض کنید در یک پروژه Laravel می‌خواهید سیستم کامنت طراحی کنید. کاربران باید بتوانند برای مقاله‌ها، محصولات، ویدئوها و حتی تیکت‌ها کامنت بگذارند. یک راه ساده اما ضعیف این است که برای هرکدام جدول جداگانه بسازیم؛ مثل post_comments، product_comments، video_comments و ticket_comments. این روش در ابتدا قابل فهم است، اما خیلی زود باعث تکرار ساختار، پیچیدگی Queryها، افزایش Migrationها و سخت شدن توسعه می‌شود.

راه حرفه‌ای‌تر استفاده از Polymorphic Relationship یا رابطه چندشکلی در Eloquent است. در این مدل، یک جدول عمومی مثل comments ساخته می‌شود و هر کامنت می‌تواند به هر مدل قابل کامنت‌گذاری متصل شود. یعنی یک کامنت ممکن است متعلق به Post باشد، کامنت دیگر متعلق به Product و کامنت بعدی متعلق به Video.

طبق مستندات رسمی Laravel، رابطه یک‌به‌چند Polymorphic شبیه رابطه معمولی یک‌به‌چند است، با این تفاوت که مدل فرزند می‌تواند از طریق یک ارتباط واحد به بیش از یک نوع مدل والد متعلق باشد. مطالعه مستندات رسمی Laravel درباره روابط Eloquent

این قابلیت برای شرکت‌های تولید نرم‌افزار اهمیت زیادی دارد، چون بسیاری از سیستم‌های سازمانی و تجاری با موجودیت‌های قابل اشتراک سروکار دارند؛ مثل کامنت، فایل، تصویر، تگ، لاگ فعالیت، نوتیفیکیشن، لایک، امتیازدهی، ضمیمه‌ها و تاریخچه تغییرات. اگر این بخش‌ها درست طراحی نشوند، پروژه به‌مرور با جدول‌های تکراری، منطق پراکنده و هزینه نگهداری بالا مواجه می‌شود.

در این مقاله، به‌صورت کامل و فنی بررسی می‌کنیم Polymorphic در Laravel چیست، چه زمانی باید از آن استفاده کنیم، چه انواعی دارد، چطور Migration و Modelها را طراحی کنیم، چه تفاوتی با رابطه‌های معمولی دارد، در چه سناریوهایی خطرناک یا نامناسب است و چگونه در پروژه‌های حرفه‌ای Laravel از آن به شکل بهینه و قابل نگهداری استفاده کنیم. 🚀

Polymorphic در Laravel چیست؟

Polymorphic Relationship در Laravel نوعی رابطه Eloquent است که اجازه می‌دهد یک مدل به چند نوع مدل مختلف متصل شود. در رابطه‌های معمولی، یک مدل فرزند معمولاً فقط به یک نوع مدل والد وابسته است. برای مثال، هر کامنت فقط به یک مقاله متصل می‌شود:

posts
comments

 

و جدول comments ستونی مثل post_id دارد.

اما اگر همان کامنت قرار باشد به مقاله، محصول، ویدئو و تیکت متصل شود، رابطه معمولی کافی نیست. در رابطه Polymorphic، به‌جای یک ستون مثل post_id، معمولاً دو ستون داریم:

commentable_id
commentable_type

 

معنی این دو ستون:

ستونکاربرد
commentable_idشناسه رکورد والد، مثلاً ID مقاله یا محصول
commentable_typeنوع مدل والد، مثلاً App\Models\Post یا App\Models\Product

بنابراین یک ردیف در جدول comments می‌تواند این‌گونه باشد:

idbodycommentable_idcommentable_type
1متن کامنت15App\Models\Post
2متن کامنت8App\Models\Product
3متن کامنت4App\Models\Video

اینجا هر سه رکورد در یک جدول هستند، اما به مدل‌های متفاوتی وصل شده‌اند.

چرا از Polymorphic Relationship استفاده می‌کنیم؟

روابط Polymorphic برای جلوگیری از تکرار ساختار دیتابیس و کد استفاده می‌شوند. فرض کنید می‌خواهید سیستم فایل پیوست داشته باشید. فایل‌ها ممکن است به این مدل‌ها متصل شوند:

  • کاربر
  • محصول
  • مقاله
  • تیکت
  • فاکتور
  • سفارش
  • قرارداد

اگر برای هرکدام جدول جداگانه بسازید، ساختار دیتابیس پیچیده و تکراری می‌شود:

user_files
product_files
post_files
ticket_files
invoice_files
order_files
contract_files

 

اما با Polymorphic می‌توانید یک جدول عمومی داشته باشید:

attachments
attachable_id
attachable_type

 

مزایای مهم Polymorphic:

مزیتتوضیح
کاهش تکرار جدول‌هایک جدول مشترک برای چند مدل
کاهش تکرار کدرابطه مشابه در چند مدل استفاده می‌شود
توسعه‌پذیری بالااضافه کردن مدل جدید ساده‌تر است
طراحی انعطاف‌پذیرمناسب موجودیت‌های عمومی مثل کامنت، فایل، تگ
هماهنگی با EloquentLaravel متدهای آماده مثل morphTo و morphMany دارد
مناسب معماری شرکتیماژول‌های عمومی راحت‌تر طراحی می‌شوند

اما این رابطه همیشه بهترین انتخاب نیست. در بخش‌های بعدی توضیح می‌دهیم چه زمانی استفاده از Polymorphic مناسب است و چه زمانی بهتر است رابطه معمولی طراحی شود.

مثال ساده Polymorphic: سیستم کامنت

فرض کنید در یک سایت شرکتی یا فروشگاهی می‌خواهید کاربران بتوانند روی مقاله‌ها و محصولات کامنت بگذارند.

مدل‌ها:

Post
Product
Comment

 

هر Post چند کامنت دارد. هر Product هم چند کامنت دارد. اما هر Comment فقط به یک والد متصل است؛ یا مقاله یا محصول.

ساختار جدول comments:

id
body
commentable_id
commentable_type
created_at
updated_at

 

در اینجا نام رابطه را commentable گذاشته‌ایم؛ یعنی چیزی که قابلیت کامنت گرفتن دارد.

ساخت Migration برای رابطه Polymorphic

برای ساخت جدول کامنت‌ها:

 

php artisan make:migration create_comments_table

 

نمونه Migration:

 

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('comments', function (Blueprint $table) {
            $table->id();
            $table->text('body');

            $table->morphs('commentable');

            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('comments');
    }
};

 

متد morphs('commentable') معمولاً دو ستون ایجاد می‌کند:

commentable_id
commentable_type

 

طبق مستندات رسمی Laravel درباره Migrationها، Schema Builder لاراول امکاناتی برای ساخت و تغییر جدول‌ها به‌صورت مستقل از نوع دیتابیس ارائه می‌دهد و در روابط Polymorphic نیز ستون‌های مربوط به Morph از طریق متدهایی مثل morphs قابل ایجاد هستند. مطالعه مستندات رسمی Laravel درباره Migrations

اگر رابطه اختیاری باشد، می‌توانید از nullableMorphs استفاده کنید:

 

$table->nullableMorphs('commentable');

 

برای UUID یا ULID نیز متدهای مخصوص وجود دارد؛ مانند:

 

$table->uuidMorphs('commentable');
$table->ulidMorphs('commentable');

 

انتخاب نوع ستون باید با نوع کلید اصلی مدل‌های شما هماهنگ باشد.

تعریف رابطه در مدل Comment با morphTo

در مدل Comment باید مشخص کنیم که این کامنت می‌تواند به مدل‌های مختلفی متعلق باشد. برای این کار از morphTo استفاده می‌کنیم.

 

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;

class Comment extends Model
{
    protected $fillable = [
        'body',
    ];

    public function commentable(): MorphTo
    {
        return $this->morphTo();
    }
}

 

متد commentable رابطه معکوس Polymorphic است. یعنی از روی یک کامنت می‌توانیم والد آن را پیدا کنیم:

 

$comment = Comment::find(1);

$parent = $comment->commentable;

 

اگر commentable_type برابر App\Models\Post باشد، $parent یک مدل Post خواهد بود. اگر برابر App\Models\Product باشد، $parent یک مدل Product خواهد بود.

تعریف رابطه در مدل Post با morphMany

حالا باید در مدل Post مشخص کنیم که هر مقاله می‌تواند چند کامنت داشته باشد:

 

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;

class Post extends Model
{
    public function comments(): MorphMany
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

 

در مدل Product نیز همین رابطه را تعریف می‌کنیم:

 

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;

class Product extends Model
{
    public function comments(): MorphMany
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

 

حالا هم مقاله و هم محصول می‌توانند کامنت داشته باشند، بدون اینکه جدول‌های جداگانه بسازیم.

ایجاد رکورد در رابطه Polymorphic

برای ساخت کامنت برای یک مقاله:

 

$post = Post::findOrFail(1);

$post->comments()->create([
    'body' => 'این مقاله بسیار کاربردی بود.',
]);

 

Laravel به‌صورت خودکار مقدارهای زیر را پر می‌کند:

commentable_id = ID مقاله
commentable_type = کلاس مدل Post

 

برای محصول:

 

$product = Product::findOrFail(1);

$product->comments()->create([
    'body' => 'کیفیت این محصول عالی است.',
]);

 

اینجا نیز Laravel به‌صورت خودکار commentable_id و commentable_type را بر اساس مدل Product پر می‌کند.

خواندن داده‌ها در رابطه Polymorphic

دریافت کامنت‌های مقاله:

 

$post = Post::with('comments')->findOrFail(1);

foreach ($post->comments as $comment) {
    echo $comment->body;
}

 

دریافت والد یک کامنت:

 

$comment = Comment::findOrFail(1);

$parent = $comment->commentable;

 

اگر والد یک مقاله باشد:

 

echo $comment->commentable->title;

 

اما باید توجه کنید که والد ممکن است انواع مختلفی داشته باشد. بنابراین در کدهای حرفه‌ای بهتر است نوع آن را بررسی کنید:

 

if ($comment->commentable instanceof Post) {
    echo $comment->commentable->title;
}

if ($comment->commentable instanceof Product) {
    echo $comment->commentable->name;
}

 

انواع روابط Polymorphic در Laravel

Laravel چند نوع رابطه Polymorphic ارائه می‌دهد. مهم‌ترین آن‌ها:

نوع رابطهمتدهامثال
یک‌به‌یک PolymorphicmorphOne, morphToتصویر اصلی برای کاربر یا محصول
یک‌به‌چند PolymorphicmorphMany, morphToکامنت‌ها برای مقاله و محصول
چندبه‌چند PolymorphicmorphToMany, morphedByManyتگ‌ها برای مقاله و ویدئو
One of Many PolymorphiclatestOfMany, oldestOfMany, ofManyآخرین تصویر یا بهترین قیمت مرتبط

مستندات رسمی Laravel انواع مختلف روابط Eloquent را پوشش می‌دهد، از جمله One To One Polymorphic، One To Many Polymorphic و Many To Many Polymorphic. مطالعه مستندات رسمی Laravel درباره روابط چندشکلی

رابطه یک‌به‌یک Polymorphic با morphOne

رابطه یک‌به‌یک Polymorphic زمانی کاربرد دارد که یک مدل مرتبط بتواند متعلق به چند نوع مدل باشد، اما هر والد فقط یک رکورد از آن داشته باشد.

مثال: هر کاربر، محصول یا مقاله می‌تواند یک تصویر اصلی داشته باشد.

مدل‌ها:

User
Product
Post
Image

 

جدول images:

 

Schema::create('images', function (Blueprint $table) {
    $table->id();
    $table->string('path');
    $table->morphs('imageable');
    $table->timestamps();
});

 

مدل Image:

 

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;

class Image extends Model
{
    protected $fillable = [
        'path',
    ];

    public function imageable(): MorphTo
    {
        return $this->morphTo();
    }
}

 

مدل Product:

 

use Illuminate\Database\Eloquent\Relations\MorphOne;

class Product extends Model
{
    public function image(): MorphOne
    {
        return $this->morphOne(Image::class, 'imageable');
    }
}

 

مدل Post:

 

use Illuminate\Database\Eloquent\Relations\MorphOne;

class Post extends Model
{
    public function image(): MorphOne
    {
        return $this->morphOne(Image::class, 'imageable');
    }
}

 

ایجاد تصویر برای محصول:

 

$product->image()->create([
    'path' => 'products/product-1.jpg',
]);

 

دریافت تصویر:

 

$image = $product->image;

 

این روش برای Avatar، تصویر شاخص، فایل اصلی یا تنظیمات تک‌ردیفی مشترک کاربرد دارد.

رابطه یک‌به‌چند Polymorphic با morphMany

رابطه یک‌به‌چند Polymorphic رایج‌ترین نوع رابطه چندشکلی است.

مثال‌های رایج:

  • یک مقاله چند کامنت دارد.
  • یک محصول چند کامنت دارد.
  • یک تیکت چند فایل پیوست دارد.
  • یک کاربر چند لاگ فعالیت دارد.
  • یک فاکتور چند فایل ضمیمه دارد.

نمونه فایل پیوست:

 

Schema::create('attachments', function (Blueprint $table) {
    $table->id();
    $table->string('file_name');
    $table->string('file_path');
    $table->morphs('attachable');
    $table->timestamps();
});

 

مدل Attachment:

 

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;

class Attachment extends Model
{
    protected $fillable = [
        'file_name',
        'file_path',
    ];

    public function attachable(): MorphTo
    {
        return $this->morphTo();
    }
}

 

مدل Ticket:

 

use Illuminate\Database\Eloquent\Relations\MorphMany;

class Ticket extends Model
{
    public function attachments(): MorphMany
    {
        return $this->morphMany(Attachment::class, 'attachable');
    }
}

 

مدل Invoice:

 

use Illuminate\Database\Eloquent\Relations\MorphMany;

class Invoice extends Model
{
    public function attachments(): MorphMany
    {
        return $this->morphMany(Attachment::class, 'attachable');
    }
}

 

استفاده:

 

$ticket->attachments()->create([
    'file_name' => 'error-screenshot.png',
    'file_path' => 'tickets/error-screenshot.png',
]);

 

رابطه چندبه‌چند Polymorphic با morphToMany

رابطه چندبه‌چند Polymorphic کمی پیچیده‌تر است. این رابطه زمانی کاربرد دارد که چند مدل مختلف بتوانند با یک مدل مشترک رابطه چندبه‌چند داشته باشند.

مثال معروف: سیستم تگ.

مدل‌ها:

Post
Video
Tag

 

هر مقاله چند تگ دارد. هر ویدئو هم چند تگ دارد. هر تگ نیز می‌تواند به چند مقاله و چند ویدئو متصل باشد.

جدول‌ها:

posts
videos
tags
taggables

 

جدول واسط taggables:

 

Schema::create('taggables', function (Blueprint $table) {
    $table->id();

    $table->foreignId('tag_id')->constrained()->cascadeOnDelete();

    $table->morphs('taggable');

    $table->timestamps();

    $table->unique(['tag_id', 'taggable_id', 'taggable_type']);
});

 

مدل Tag:

 

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphedByMany;

class Tag extends Model
{
    protected $fillable = [
        'name',
        'slug',
    ];

    public function posts(): MorphedByMany
    {
        return $this->morphedByMany(Post::class, 'taggable');
    }

    public function videos(): MorphedByMany
    {
        return $this->morphedByMany(Video::class, 'taggable');
    }
}

 

مدل Post:

 

use Illuminate\Database\Eloquent\Relations\MorphToMany;

class Post extends Model
{
    public function tags(): MorphToMany
    {
        return $this->morphToMany(Tag::class, 'taggable');
    }
}

 

مدل Video:

 

use Illuminate\Database\Eloquent\Relations\MorphToMany;

class Video extends Model
{
    public function tags(): MorphToMany
    {
        return $this->morphToMany(Tag::class, 'taggable');
    }
}

 

اتصال تگ به مقاله:

 

$post->tags()->attach($tagId);

 

همگام‌سازی تگ‌ها:

 

$post->tags()->sync([1, 2, 3]);

 

دریافت تگ‌های ویدئو:

 

$tags = $video->tags;

 

در مستندات Laravel، رابطه Many To Many Polymorphic با مثال Post، Video و Tag توضیح داده شده و برای این سناریو از morphToMany و morphedByMany استفاده می‌شود. مطالعه مستندات رسمی Laravel درباره Many To Many Polymorphic

تفاوت morphToMany و morphedByMany

در رابطه چندبه‌چند Polymorphic، دو سمت رابطه متفاوت تعریف می‌شوند.

متدکجا استفاده می‌شود؟مثال
morphToManyدر مدل‌هایی که تگ‌پذیر هستندPost, Video
morphedByManyدر مدل مشترک یا هدف رابطهTag

در Post:

 

public function tags(): MorphToMany
{
    return $this->morphToMany(Tag::class, 'taggable');
}

 

در Tag:

 

public function posts(): MorphedByMany
{
    return $this->morphedByMany(Post::class, 'taggable');
}

 

یعنی مقاله می‌گوید «من چند تگ دارم»، و تگ می‌گوید «من به چند مقاله متصل هستم».

Morph Map در Laravel چیست؟

به‌صورت پیش‌فرض، Laravel در ستون *_type نام کامل کلاس مدل را ذخیره می‌کند. مثلاً:

App\Models\Post
App\Models\Product

 

این کار ساده است، اما چند مشکل دارد:

  • اگر Namespace مدل تغییر کند، داده‌های قدیمی مشکل پیدا می‌کنند.
  • مقدار ذخیره‌شده طولانی است.
  • ساختار داخلی کد در دیتابیس ذخیره می‌شود.
  • وابستگی دیتابیس به نام کلاس‌ها زیاد می‌شود.

برای حل این مشکل می‌توان از Morph Map استفاده کرد. با Morph Map می‌توانید نام‌های کوتاه و پایدار تعریف کنید:

 

use Illuminate\Database\Eloquent\Relations\Relation;

Relation::enforceMorphMap([
    'post' => \App\Models\Post::class,
    'product' => \App\Models\Product::class,
    'video' => \App\Models\Video::class,
]);

 

بعد از این تنظیم، در ستون commentable_type به‌جای App\Models\Post مقدار post ذخیره می‌شود.

این روش برای پروژه‌های حرفه‌ای بسیار توصیه می‌شود، مخصوصاً اگر دیتابیس بلندمدت، API عمومی یا احتمال Refactor Namespace وجود دارد.

محل مناسب برای تعریف Morph Map معمولاً یکی از Service Providerهاست، مثل AppServiceProvider:

 

use Illuminate\Database\Eloquent\Relations\Relation;

public function boot(): void
{
    Relation::enforceMorphMap([
        'post' => \App\Models\Post::class,
        'product' => \App\Models\Product::class,
    ]);
}

 

Eager Loading در روابط Polymorphic

مثل سایر رابطه‌های Eloquent، اگر روابط Polymorphic را بدون Eager Loading استفاده کنید، ممکن است با مشکل N+1 Query روبه‌رو شوید.

مثال بد:

 

$comments = Comment::latest()->get();

foreach ($comments as $comment) {
    echo $comment->commentable->title;
}

 

در این حالت، برای هر کامنت ممکن است یک Query جداگانه برای والد اجرا شود.

روش بهتر:

 

$comments = Comment::with('commentable')->latest()->get();

 

اما چون commentable می‌تواند چند نوع مدل باشد، Laravel باید برای هر نوع مدل Query جداگانه اجرا کند. مثلاً اگر کامنت‌ها به Post و Product متصل باشند، معمولاً Queryهای جدا برای Postها و Productها اجرا می‌شود.

برای سناریوهای پیچیده‌تر، می‌توانید روی نوع‌های مختلف محدودیت اعمال کنید.

morphWith برای Eager Loading تو در تو

فرض کنید کامنت‌ها به Post و Product متصل هستند. برای Post می‌خواهید نویسنده را هم Eager Load کنید و برای Product می‌خواهید دسته‌بندی را بگیرید.

در رابطه morphTo می‌توان از morphWith استفاده کرد:

 

use Illuminate\Database\Eloquent\Relations\MorphTo;

$comments = Comment::query()
    ->with([
        'commentable' => function (MorphTo $morphTo) {
            $morphTo->morphWith([
                Post::class => ['author'],
                Product::class => ['category'],
            ]);
        },
    ])
    ->get();

 

این روش برای کاهش Queryهای اضافی در پروژه‌های بزرگ بسیار مهم است.

Query روی رابطه Polymorphic با whereHasMorph

گاهی می‌خواهید روی والدهای Polymorphic شرط بگذارید. مثلاً کامنت‌هایی را پیدا کنید که والد آن‌ها مقاله منتشرشده یا محصول فعال است.

Laravel برای این کار متدهایی مثل whereHasMorph ارائه می‌دهد.

نمونه:

 

$comments = Comment::whereHasMorph(
    'commentable',
    [Post::class, Product::class],
    function ($query) {
        $query->where('status', 'published');
    }
)->get();

 

اگر شرط برای هر نوع متفاوت باشد:

 

$comments = Comment::whereHasMorph(
    'commentable',
    [Post::class, Product::class],
    function ($query, string $type) {
        if ($type === Post::class) {
            $query->where('is_published', true);
        }

        if ($type === Product::class) {
            $query->where('is_active', true);
        }
    }
)->get();

 

این قابلیت برای پنل‌های مدیریتی، فیلترهای جستجو و گزارش‌گیری کاربرد دارد.

one of many در روابط Polymorphic

گاهی یک مدل چند رکورد مرتبط دارد، اما شما فقط یکی از آن‌ها را می‌خواهید؛ مثلاً آخرین تصویر، قدیمی‌ترین فایل یا تصویر اصلی.

Laravel برای رابطه‌های Has One of Many امکاناتی مثل latestOfMany، oldestOfMany و ofMany ارائه می‌دهد و این مفهوم می‌تواند در برخی روابط Polymorphic نیز استفاده شود. در مستندات رسمی Laravel، بخش One of Many و روابط Polymorphic توضیح می‌دهد که می‌توان از این قابلیت برای دریافت یک مدل خاص از میان چند مدل مرتبط استفاده کرد. مطالعه مستندات رسمی Laravel درباره One of Many

مثال:

 

use Illuminate\Database\Eloquent\Relations\MorphOne;

class Product extends Model
{
    public function latestImage(): MorphOne
    {
        return $this->morphOne(Image::class, 'imageable')->latestOfMany();
    }
}

 

یا دریافت تصویر اصلی بر اساس یک ستون:

 

public function primaryImage(): MorphOne
{
    return $this->morphOne(Image::class, 'imageable')
        ->ofMany('id', 'max', function ($query) {
            $query->where('is_primary', true);
        });
}

 

این قابلیت برای گالری تصاویر، فایل‌های نسخه‌بندی‌شده و رکوردهای تاریخی بسیار مفید است.

طراحی دیتابیس در Polymorphic

طراحی دیتابیس در روابط Polymorphic باید با دقت انجام شود؛ چون برخلاف Foreign Keyهای معمولی، ستون *_type می‌تواند به چند جدول مختلف اشاره کند و دیتابیس به‌صورت مستقیم نمی‌تواند روی آن Foreign Key ساده تعریف کند.

نکات مهم طراحی

نکتهتوضیح
Index ترکیبیروی *_type و *_id Index داشته باشید
Morph Mapاز نام‌های کوتاه و پایدار استفاده کنید
نوع ID هماهنگاگر مدل‌ها UUID دارند، از uuidMorphs استفاده کنید
حذف داده‌هاحذف والدها را با Observer، Event یا منطق Service مدیریت کنید
Unique Constraintدر Pivotهای Polymorphic از Unique مناسب استفاده کنید
Soft Deleteاگر والد Soft Delete دارد، رفتار فرزندها را مشخص کنید

نمونه Index:

 

$table->index(['commentable_type', 'commentable_id']);

 

متد morphs معمولاً Index ایجاد می‌کند، اما در طراحی‌های سفارشی بهتر است این موضوع را بررسی کنید.

محدودیت مهم: Foreign Key مستقیم نداریم

یکی از مهم‌ترین نکات روابط Polymorphic این است که دیتابیس نمی‌تواند به‌سادگی برای commentable_id یک Foreign Key واحد تعریف کند؛ چون این ستون ممکن است به جدول‌های مختلفی اشاره کند.

برای مثال:

commentable_id = 1
commentable_type = posts

 

یا:

commentable_id = 1
commentable_type = products

 

یک ستون نمی‌تواند همزمان Foreign Key به posts.id و products.id باشد. بنابراین حفظ یکپارچگی داده بیشتر بر عهده برنامه، Eloquent، تست‌ها و منطق حذف/به‌روزرسانی است.

این محدودیت باعث می‌شود Polymorphic برای همه سناریوها مناسب نباشد. اگر یک رابطه بسیار حساس مالی یا حقوقی دارید و نیاز به Constraint سخت دیتابیس دارید، باید با دقت بیشتری تصمیم بگیرید.

حذف داده‌های مرتبط در Polymorphic

اگر یک مقاله حذف شود، با کامنت‌های آن چه باید کرد؟ این سؤال در رابطه‌های Polymorphic مهم است، چون Cascade Delete دیتابیس به‌سادگی قابل استفاده نیست.

روش‌های رایج:

1. حذف در Model Event یا Observer

 

class Post extends Model
{
    protected static function booted(): void
    {
        static::deleting(function (Post $post) {
            $post->comments()->delete();
        });
    }
}

 

2. حذف در Service

 

DB::transaction(function () use ($post) {
    $post->comments()->delete();
    $post->delete();
});

 

3. Soft Delete

اگر داده حساس است، بهتر است والد و فرزندها Soft Delete شوند.

4. نگه‌داشتن داده برای Audit

در سیستم‌های سازمانی، شاید لازم باشد کامنت‌ها یا لاگ‌ها حتی بعد از حذف والد حفظ شوند. در این حالت باید رفتار نمایش و Query مشخص شود.

برای پروژه‌های حرفه‌ای، بهتر است سیاست حذف داده‌ها برای هر رابطه Polymorphic به‌صورت واضح مستند شود.

مثال کاربردی: سیستم فایل پیوست چندشکلی

در نرم‌افزارهای شرکتی، فایل‌ها معمولاً به موجودیت‌های مختلف وصل می‌شوند:

  • تیکت
  • فاکتور
  • قرارداد
  • پروژه
  • کاربر
  • سفارش

به‌جای ساخت جدول جدا برای هرکدام، می‌توان از Polymorphic استفاده کرد.

Migration:

 

Schema::create('attachments', function (Blueprint $table) {
    $table->id();
    $table->string('disk')->default('public');
    $table->string('file_name');
    $table->string('file_path');
    $table->string('mime_type')->nullable();
    $table->unsignedBigInteger('size')->nullable();
    $table->morphs('attachable');
    $table->timestamps();
});

 

مدل Attachment:

 

class Attachment extends Model
{
    protected $fillable = [
        'disk',
        'file_name',
        'file_path',
        'mime_type',
        'size',
    ];

    public function attachable(): MorphTo
    {
        return $this->morphTo();
    }
}

 

مدل Ticket:

 

class Ticket extends Model
{
    public function attachments(): MorphMany
    {
        return $this->morphMany(Attachment::class, 'attachable');
    }
}

 

مدل Invoice:

 

class Invoice extends Model
{
    public function attachments(): MorphMany
    {
        return $this->morphMany(Attachment::class, 'attachable');
    }
}

 

استفاده:

 

$invoice->attachments()->create([
    'disk' => 'private',
    'file_name' => 'invoice.pdf',
    'file_path' => 'invoices/2026/invoice.pdf',
    'mime_type' => 'application/pdf',
    'size' => 245000,
]);

 

این ساختار برای پنل‌های مدیریتی، CRM، ERP و سیستم‌های اتوماسیون بسیار کاربردی است.

مثال کاربردی: سیستم Activity Log

یکی دیگر از کاربردهای عالی Polymorphic، ثبت لاگ فعالیت برای موجودیت‌های مختلف است.

جدول:

 

Schema::create('activity_logs', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
    $table->string('action');
    $table->json('properties')->nullable();
    $table->morphs('subject');
    $table->timestamps();
});

 

مدل ActivityLog:

 

class ActivityLog extends Model
{
    protected $fillable = [
        'user_id',
        'action',
        'properties',
    ];

    protected function casts(): array
    {
        return [
            'properties' => 'array',
        ];
    }

    public function subject(): MorphTo
    {
        return $this->morphTo();
    }
}

 

مدل Order:

 

class Order extends Model
{
    public function activities(): MorphMany
    {
        return $this->morphMany(ActivityLog::class, 'subject');
    }
}

 

ثبت لاگ:

 

$order->activities()->create([
    'user_id' => auth()->id(),
    'action' => 'order_created',
    'properties' => [
        'total_price' => $order->total_price,
    ],
]);

 

این طراحی باعث می‌شود لاگ فعالیت‌ها برای سفارش، فاکتور، کاربر، محصول و سایر مدل‌ها در یک جدول یکپارچه ذخیره شود.

مثال کاربردی: سیستم Like چندشکلی

فرض کنید کاربران بتوانند مقاله، محصول و کامنت را Like کنند.

Migration:

 

Schema::create('likes', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained()->cascadeOnDelete();
    $table->morphs('likeable');
    $table->timestamps();

    $table->unique(['user_id', 'likeable_id', 'likeable_type']);
});

 

مدل Like:

 

class Like extends Model
{
    protected $fillable = [
        'user_id',
    ];

    public function likeable(): MorphTo
    {
        return $this->morphTo();
    }
}

 

مدل Post:

 

class Post extends Model
{
    public function likes(): MorphMany
    {
        return $this->morphMany(Like::class, 'likeable');
    }
}

 

Like کردن:

 

$post->likes()->firstOrCreate([
    'user_id' => auth()->id(),
]);

 

تعداد Likeها:

 

$count = $post->likes()->count();

 

این طراحی از ایجاد جدول‌های جدا مثل post_likes و product_likes جلوگیری می‌کند.

Polymorphic و API Resource

وقتی داده Polymorphic را در API خروجی می‌دهید، باید ساختار پاسخ را دقیق طراحی کنید. چون والد رابطه می‌تواند مدل‌های مختلفی باشد.

مثال:

 

class CommentResource extends JsonResource
{
    public function toArray($request): array
    {
        return [
            'id' => $this->id,
            'body' => $this->body,
            'commentable' => [
                'type' => class_basename($this->commentable_type),
                'id' => $this->commentable_id,
                'title' => $this->whenLoaded('commentable', function () {
                    return $this->commentable->title ?? $this->commentable->name ?? null;
                }),
            ],
        ];
    }
}

 

در APIهای حرفه‌ای بهتر است به‌جای خروجی دادن مستقیم نام کلاس PHP، از نوع‌های پایدارتر استفاده کنید:

 

{
  "type": "post",
  "id": 12
}

 

اینجا Morph Map نیز کمک می‌کند.

Polymorphic و Performance

روابط Polymorphic قدرتمند هستند، اما اگر بدون دقت استفاده شوند، می‌توانند Performance را تحت تأثیر قرار دهند.

نکات مهم Performance

نکتهتوضیح
Eager Loadingبرای جلوگیری از N+1 از with استفاده کنید
Index مناسبروی ستون‌های morph Index داشته باشید
Morph Mapمقدار type را کوتاه‌تر و پایدارتر می‌کند
محدود کردن نوع‌هادر Queryها نوع‌های مورد نیاز را مشخص کنید
Queryهای سنگینگزارش‌گیری‌های پیچیده را جدا طراحی کنید
Cacheبرای داده‌های پرتکرار از Cache استفاده کنید
Paginationلیست‌های بزرگ را paginate کنید

مثال:

 

$comments = Comment::with('commentable')
    ->latest()
    ->paginate(20);

 

اگر حجم داده زیاد است، از Queryهای بدون محدودیت مثل all() پرهیز کنید.

Polymorphic و تست‌نویسی

برای رابطه‌های Polymorphic باید تست بنویسید تا مطمئن شوید رابطه‌ها درست کار می‌کنند.

نمونه تست:

 

public function test_post_can_have_comments(): void
{
    $post = Post::factory()->create();

    $post->comments()->create([
        'body' => 'Test comment',
    ]);

    $this->assertCount(1, $post->comments);

    $this->assertDatabaseHas('comments', [
        'body' => 'Test comment',
        'commentable_id' => $post->id,
        'commentable_type' => Post::class,
    ]);
}

 

اگر از Morph Map استفاده می‌کنید، مقدار commentable_type ممکن است post باشد، نه نام کامل کلاس:

 

$this->assertDatabaseHas('comments', [
    'commentable_type' => 'post',
]);

 

تست‌های مهم:

  • ایجاد رابطه از والد
  • خواندن والد از فرزند
  • حذف والد و رفتار فرزند
  • Eager Loading
  • Query با whereHasMorph
  • عملکرد Morph Map
  • Unique Constraint در Pivotهای Polymorphic

Polymorphic در پروژه‌های شرکتی

در پروژه‌های شرکتی، روابط Polymorphic معمولاً در ماژول‌های عمومی و قابل استفاده مجدد کاربرد دارند.

ماژولمدل Polymorphicمدل‌های والد احتمالی
کامنتCommentمقاله، محصول، تیکت، پروژه
فایل پیوستAttachmentفاکتور، قرارداد، تیکت، کاربر
تصویرImageمحصول، مقاله، کاربر
لاگ فعالیتActivityLogسفارش، فاکتور، کاربر، محصول
تگTagمقاله، ویدئو، محصول
لایکLikeمقاله، کامنت، محصول
نوتیفیکیشن داخلیNotificationسفارش، تیکت، پرداخت
امتیازدهیRatingمحصول، دوره، سرویس
یادداشتNoteمشتری، پروژه، قرارداد
تاریخچه تغییراتRevisionهر مدل مهم سازمانی

این طراحی باعث می‌شود ماژول‌های عمومی مثل فایل، کامنت و لاگ فقط یک بار پیاده‌سازی شوند و در بخش‌های مختلف سیستم استفاده شوند.

چه زمانی از Polymorphic استفاده نکنیم؟

با وجود مزایای زیاد، Polymorphic همیشه بهترین گزینه نیست.

1. وقتی فقط دو مدل با منطق کاملاً متفاوت دارید

اگر رابطه‌ها فقط ظاهراً شبیه هستند اما قوانین، فیلدها و رفتارهای کاملاً متفاوت دارند، جدول مشترک ممکن است باعث پیچیدگی شود.

2. وقتی نیاز جدی به Foreign Key دیتابیس دارید

در رابطه Polymorphic، Foreign Key مستقیم برای چند جدول مختلف ساده نیست. اگر یکپارچگی سخت دیتابیس بسیار مهم است، باید با دقت تصمیم بگیرید.

3. وقتی Queryهای تحلیلی بسیار پیچیده دارید

گزارش‌گیری روی چند نوع مدل مختلف در یک رابطه Polymorphic می‌تواند پیچیده‌تر شود.

4. وقتی نوع‌های والد زیاد و بی‌قاعده می‌شوند

اگر هر چیزی را Polymorphic کنید، سیستم مبهم و سخت‌دیباگ می‌شود.

5. وقتی رابطه واقعاً عمومی نیست

Polymorphic برای موجودیت‌های عمومی مناسب است؛ مثل کامنت، فایل، تگ و لاگ. اگر رابطه خاص یک دامنه است، رابطه معمولی ممکن است بهتر باشد.

خطاهای رایج در روابط Polymorphic

1. انتخاب نام مبهم برای رابطه

نام‌هایی مثل modelable یا relationable خوانایی کمی دارند. بهتر است نام رابطه معنا داشته باشد:

commentable
imageable
attachable
taggable
likeable
subject

 

2. استفاده نکردن از Morph Map

در پروژه‌های بلندمدت، ذخیره نام کامل کلاس در دیتابیس می‌تواند در آینده مشکل‌ساز شود.

3. نداشتن Index مناسب

بدون Index روی *_type و *_id، Queryها در داده‌های زیاد کند می‌شوند.

4. نادیده گرفتن N+1 Query

روابط Polymorphic نیز مثل سایر روابط Eloquent نیاز به Eager Loading دارند.

5. حذف والد بدون مدیریت فرزندها

چون Cascade Foreign Key ساده ندارید، باید حذف داده‌های مرتبط را با Service، Observer یا Event مدیریت کنید.

6. ذخیره داده حساس در مدل عمومی

اگر جدول Polymorphic عمومی است، مراقب سطح دسترسی و داده‌های حساس باشید.

7. استفاده بیش از حد از Polymorphic

هر رابطه‌ای را نباید Polymorphic کرد. استفاده افراطی باعث مبهم شدن معماری می‌شود.

بهترین روش‌های استفاده از Polymorphic در Laravel

1. فقط برای موجودیت‌های واقعاً مشترک استفاده کنید

کامنت، فایل، تصویر، تگ، لاگ و لایک نمونه‌های مناسب هستند.

2. نام رابطه را دقیق انتخاب کنید

نام رابطه باید مفهوم تجاری داشته باشد؛ مثل commentable یا attachable.

3. از Morph Map استفاده کنید

برای جلوگیری از وابستگی دیتابیس به Namespace کلاس‌ها، Morph Map تعریف کنید.

4. Index را جدی بگیرید

ستون‌های *_type و *_id باید برای Queryهای پرتکرار بهینه شوند.

5. رفتار حذف را مشخص کنید

تصمیم بگیرید با حذف والد، فرزندها حذف شوند، Soft Delete شوند یا باقی بمانند.

6. API را از نام کلاس PHP جدا کنید

در خروجی API از نوع‌های پایدار مثل post و product استفاده کنید، نه App\Models\Post.

7. Queryهای Polymorphic را تست کنید

به‌خصوص Queryهایی که از whereHasMorph یا Eager Loading پیچیده استفاده می‌کنند.

8. منطق تجاری را در Service نگه دارید

Model فقط رابطه را تعریف کند؛ منطق پیچیده بهتر است در Service یا Action باشد.

9. مراقب Performance باشید

برای داده‌های زیاد از Pagination، Eager Loading و Cache استفاده کنید.

10. مستندسازی کنید

در پروژه‌های تیمی، مشخص کنید هر جدول Polymorphic به چه مدل‌هایی می‌تواند متصل شود.

جدول مقایسه انواع Polymorphic در Laravel

نوع رابطهمتد سمت والدمتد سمت فرزند/هدفمثالکاربرد
یک‌به‌یکmorphOnemorphToتصویر اصلی محصول یا کاربرAvatar، تصویر شاخص
یک‌به‌چندmorphManymorphToکامنت‌های مقاله و محصولکامنت، فایل، لاگ
چندبه‌چندmorphToManymorphedByManyتگ‌های مقاله و ویدئوتگ، دسته‌بندی مشترک
یکی از چندتاmorphOne + latestOfManymorphToآخرین تصویر محصولرکورد منتخب از چند رکورد
رابطه معکوسنداردmorphToوالد کامنتیافتن مدل مالک

نمونه کامل: پیاده‌سازی کامنت Polymorphic در Laravel

Migration

 

Schema::create('comments', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
    $table->text('body');
    $table->morphs('commentable');
    $table->timestamps();
});

 

Comment Model

 

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;

class Comment extends Model
{
    protected $fillable = [
        'user_id',
        'body',
    ];

    public function commentable(): MorphTo
    {
        return $this->morphTo();
    }
}

 

Post Model

 

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;

class Post extends Model
{
    public function comments(): MorphMany
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

 

Product Model

 

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;

class Product extends Model
{
    public function comments(): MorphMany
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

 

Store Comment

 

$post = Post::findOrFail($postId);

$post->comments()->create([
    'user_id' => auth()->id(),
    'body' => request('body'),
]);

 

Read Comments

 

$post = Post::with('comments')->findOrFail($postId);

return $post->comments;

 

Read Parent

 

$comment = Comment::with('commentable')->findOrFail($commentId);

return $comment->commentable;

 

Polymorphic و سئو در پروژه‌های Laravel

Polymorphic به‌صورت مستقیم ابزار SEO نیست، اما در پروژه‌های محتوایی و فروشگاهی می‌تواند به طراحی تمیزتر ساختار محتوا کمک کند. برای مثال:

  • تگ‌ها می‌توانند بین مقاله‌ها، ویدئوها و محصولات مشترک باشند.
  • کامنت‌ها می‌توانند برای انواع محتوا یکپارچه مدیریت شوند.
  • تصاویر و فایل‌های رسانه‌ای می‌توانند ساختار مشترک داشته باشند.
  • Activity Log انتشار محتوا می‌تواند برای مدل‌های مختلف ثبت شود.
  • Sitemap یا Cache می‌تواند با Eventهای مرتبط با مدل‌های Polymorphic به‌روزرسانی شود.

مثلاً اگر Tag به‌صورت Polymorphic برای مقاله و ویدئو استفاده شود، می‌توانید صفحات آرشیو موضوعی قوی‌تری طراحی کنید. البته باید مراقب باشید ساختار URL، Canonical و داده‌های متا برای هر نوع محتوا جداگانه و دقیق مدیریت شود.

FAQ؛ سوالات متداول درباره Polymorphic در Laravel

1. Polymorphic در Laravel چیست؟

Polymorphic Relationship در Laravel نوعی رابطه Eloquent است که اجازه می‌دهد یک مدل به چند نوع مدل مختلف متصل شود. مثلاً یک کامنت می‌تواند متعلق به مقاله، محصول یا ویدئو باشد.

2. ستون‌های commentable_id و commentable_type چه کاربردی دارند؟

commentable_id شناسه مدل والد را نگه می‌دارد و commentable_type نوع مدل والد را مشخص می‌کند. این دو ستون با هم تعیین می‌کنند رکورد مربوطه به کدام مدل و کدام رکورد متصل است.

3. تفاوت morphOne و morphMany چیست؟

morphOne برای رابطه یک‌به‌یک Polymorphic استفاده می‌شود؛ مثل یک تصویر اصلی برای محصول. morphMany برای رابطه یک‌به‌چند استفاده می‌شود؛ مثل چند کامنت برای مقاله.

4. morphTo چه کاربردی دارد؟

morphTo در مدل فرزند تعریف می‌شود و رابطه معکوس را نشان می‌دهد. مثلاً در مدل Comment، متد commentable() با morphTo مشخص می‌کند کامنت به کدام مدل والد تعلق دارد.

5. morphToMany چیست؟

morphToMany برای رابطه چندبه‌چند Polymorphic استفاده می‌شود. مثال رایج آن سیستم تگ است؛ جایی که مقاله‌ها و ویدئوها می‌توانند تگ‌های مشترک داشته باشند.

6. morphedByMany چه تفاوتی با morphToMany دارد؟

morphToMany در مدل‌هایی تعریف می‌شود که به مدل مشترک وصل می‌شوند؛ مثل Post و Video. morphedByMany در مدل مشترک تعریف می‌شود؛ مثل Tag.

7. آیا در Polymorphic می‌توان Foreign Key تعریف کرد؟

به‌صورت معمول و ساده خیر؛ چون یک ستون مثل commentable_id ممکن است به جدول‌های مختلف اشاره کند. بنابراین یکپارچگی داده باید با منطق برنامه، تست، Service و سیاست حذف مناسب مدیریت شود.

8. Morph Map چیست؟

Morph Map اجازه می‌دهد به‌جای ذخیره نام کامل کلاس مثل App\Models\Post در دیتابیس، مقدار کوتاه و پایدار مثل post ذخیره شود. این کار برای پروژه‌های حرفه‌ای توصیه می‌شود.

9. آیا Polymorphic باعث کندی می‌شود؟

خود Polymorphic الزاماً کند نیست، اما اگر Index مناسب، Eager Loading و Query بهینه نداشته باشید، در داده‌های زیاد می‌تواند مشکل Performance ایجاد کند.

10. چه زمانی نباید از Polymorphic استفاده کنیم؟

اگر رابطه نیاز به Foreign Key سخت دیتابیس دارد، منطق مدل‌های مختلف کاملاً متفاوت است یا Queryهای تحلیلی پیچیده دارید، باید با احتیاط از Polymorphic استفاده کنید و شاید رابطه معمولی بهتر باشد.

11. آیا Polymorphic برای سیستم فایل مناسب است؟

بله. فایل‌ها و ضمیمه‌ها یکی از بهترین سناریوهای استفاده از Polymorphic هستند، چون ممکن است به مدل‌های مختلفی مثل تیکت، فاکتور، قرارداد و کاربر متصل شوند.

12. آیا Polymorphic برای سیستم تگ مناسب است؟

بله. برای تگ‌هایی که روی چند نوع محتوا مثل مقاله، ویدئو و محصول استفاده می‌شوند، رابطه چندبه‌چند Polymorphic انتخاب رایجی است.

جمع‌بندی

Polymorphic در Laravel یکی از قابلیت‌های قدرتمند Eloquent برای طراحی رابطه‌های انعطاف‌پذیر و قابل توسعه است. با استفاده از روابط چندشکلی می‌توان مدل‌هایی مثل کامنت، فایل، تصویر، لاگ، لایک، تگ و امتیازدهی را به چند نوع مدل مختلف متصل کرد، بدون اینکه برای هر مدل جدول و منطق جداگانه بسازیم.

این قابلیت در پروژه‌های شرکتی، فروشگاهی، محتوایی، CRM، ERP و سیستم‌های SaaS بسیار کاربردی است؛ زیرا بسیاری از ماژول‌های عمومی باید در بخش‌های مختلف سیستم استفاده شوند. به‌جای تکرار جدول‌ها و کدها، Polymorphic کمک می‌کند ساختاری متمرکزتر و قابل نگهداری‌تر داشته باشیم.

با این حال، Polymorphic باید هدفمند استفاده شود. نبود Foreign Key مستقیم، نیاز به Index مناسب، احتمال N+1 Query، پیچیدگی در گزارش‌گیری و مدیریت حذف داده‌ها از نکاتی هستند که باید جدی گرفته شوند. برای پروژه‌های حرفه‌ای، استفاده از Morph Map، Eager Loading، Service Layer، تست‌نویسی و مستندسازی رابطه‌ها بسیار توصیه می‌شود.

اگر درست طراحی شود، Polymorphic Relationship می‌تواند یکی از بهترین ابزارهای Laravel برای ساخت ماژول‌های مشترک، تمیز و توسعه‌پذیر باشد. 🧬

CTA

اگر در پروژه Laravel خود با ماژول‌هایی مثل کامنت، فایل پیوست، تگ، لاگ فعالیت، لایک یا تصاویر مشترک سروکار دارید، طراحی درست روابط Polymorphic می‌تواند ساختار دیتابیس و کد شما را بسیار تمیزتر کند. تیم ما می‌تواند در طراحی معماری Eloquent، بازطراحی دیتابیس، پیاده‌سازی روابط چندشکلی، بهینه‌سازی Queryها، کاهش N+1، طراحی API و استانداردسازی پروژه Laravel به شما کمک کند. برای بررسی فنی پروژه خود با ما تماس بگیرید و ساختار نرم‌افزار خود را حرفه‌ای‌تر و توسعه‌پذیرتر کنید. 🚀

منابع رسمی

  1. مستندات رسمی Laravel درباره Eloquent Relationships؛ برای مطالعه انواع رابطه‌های Eloquent، از جمله morphOne، morphMany، morphTo، morphToMany و morphedByMany.
    مطالعه مستندات رسمی Laravel درباره روابط Eloquent
  2. مستندات رسمی Laravel درباره Migrations؛ برای آشنایی با Schema Builder و متدهای مربوط به ساخت ستون‌های رابطه‌ای و Morph در Migrationها.
    مطالعه مستندات رسمی Laravel درباره Migrations 

 

برچسب‌ها: Polymorphic در laravel Polymorphic در لاراول Laravel Polymorphic Polymorphic Relationship Laravel روابط چندشکلی در لاراول morphOne morphMany morphTo morphToMany morphedByMany Laravel Eloquent Relationships Morph Map Laravel Eloquent Polymorphic کامنت چندشکلی لاراول تگ چندشکلی لاراول