سی ام اس نویسسی ام اس نویسیاد بگیر، سیستم خودتو بنویس
مجلهتماس با ما
سی ام اس نویسسی ام اس نویس

CMS نویس مرجعی برای آموزش برنامه نویسی وب و PHP، توسعه افزونه‌های اختصاصی وردپرس، طراحی ورک‌فلو و اتوماسیون با n8n و توسعه CMS های اختصاصی است. هدف ما ارائه آموزش‌های کاربردی و راهکارهای حرفه‌ای برای توسعه‌دهندگان، کسب‌وکارها و علاقه‌مندان به دنیای برنامه‌نویسی است.

پیوندهای سریع
محصولات فیزیکیمحصولات دیجیتالدوره‌های آموزشی
سی ام اس نویس
مجله سی ام اس نویستماس با ماپنل کاربری
سی ام اس نویس — تمامی حقوق برای سی ام اس نویس محفوظ است. © 1406 تماس با ما09307711941
One to Many در Laravel چیست؟ آموزش رابطه یک به چند در Eloquent

One to Many در Laravel چیست؟ آموزش رابطه یک به چند در Eloquent

ممدیر کل سیستم ۱۱ مهر ۱۴۰۵ ۲۰ دقیقه مطالعه ۱ بازدید
One to Many در Laravel چیست؟ آموزش رابطه یک به چند در Eloquent

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

این نوع ارتباط بین داده‌ها در طراحی دیتابیس با نام رابطه یک به چند یا One to Many شناخته می‌شود.

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

در این مقاله یاد می‌گیریم:

  • One to Many چیست؟
  • رابطه Parent و Child چگونه کار می‌کند؟
  • hasMany() چیست؟
  • belongsTo() چیست؟
  • Foreign Key کجا قرار می‌گیرد؟
  • چگونه داده‌های مرتبط را دریافت کنیم؟
  • چگونه رکورد مرتبط ایجاد کنیم؟
  • چگونه داده‌های رابطه را فیلتر کنیم؟
  • Eager Loading و Lazy Loading چیست؟
  • withCount() و whereHas() چه کاربردی دارند؟
  • چگونه از مشکل N+1 Query جلوگیری کنیم؟
  • خطاهای رایج در رابطه یک به چند چیست؟

One to Many در Laravel چیست؟

One to Many به رابطه‌ای گفته می‌شود که در آن یک رکورد از جدول اول می‌تواند با چند رکورد از جدول دوم ارتباط داشته باشد.

برای مثال تصور کنید یک فروشگاه اینترنتی داریم.

یک کاربر می‌تواند چند سفارش داشته باشد:


User

 │

 ├── Order 1

 ├── Order 2

 ├── Order 3

 └── Order 4

در این مثال:

  • User رکورد والد یا Parent است.
  • Order رکورد فرزند یا Child است.
  • هر User می‌تواند چند Order داشته باشد.
  • اما هر Order متعلق به یک User است.

بنابراین رابطه بین این دو جدول:


User 1 ─────────── N Order

است.

در Laravel برای تعریف این رابطه معمولاً از دو متد استفاده می‌کنیم:


hasMany()

در Model والد و:


belongsTo()

در Model فرزند.


# یک مثال واقعی از One to Many

فرض کنیم دو جدول داریم:

جدول users


users

--------------------------------

id

name

email

جدول orders


orders

--------------------------------

id

user_id

amount

status

created_at

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

مثلاً:


users



id    name

1     Ali

2     Reza

3     Sara

و:


orders



id    user_id    amount

1     1          500000

2     1          800000

3     1          300000

4     2          900000

در این حالت:


Ali

 ├── Order 1

 ├── Order 2

 └── Order 3



Reza

 └── Order 4



Sara

 └── بدون سفارش

این دقیقاً یک رابطه One to Many است.


# Foreign Key در رابطه One to Many

یکی از مهم‌ترین مفاهیمی که هنگام کار با رابطه یک به چند باید بدانید، Foreign Key است.

در مثال User و Order، این رابطه با ستون زیر در جدول orders ایجاد می‌شود:


user_id

این ستون به id در جدول users اشاره می‌کند.

بنابراین:


users.id

    ↑

    │

orders.user_id

نکته مهم این است که در رابطه One to Many، معمولاً Foreign Key در جدول سمت Many قرار می‌گیرد.

یعنی اگر:


User → Orders

داشته باشیم، user_id در جدول orders قرار می‌گیرد.

اگر:


Category → Products

داشته باشیم، category_id در جدول products قرار می‌گیرد.

اگر:


Post → Comments

داشته باشیم، post_id در جدول comments قرار می‌گیرد.


# ساخت Migration برای رابطه One to Many

فرض کنیم می‌خواهیم سیستم کاربران و سفارش‌ها را ایجاد کنیم.

ابتدا Migration سفارش‌ها را ایجاد می‌کنیم:


php artisan make:migration create_orders_table

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


Schema::create('orders', function (Blueprint $table) {

    $table->id();



    $table->foreignId('user_id')

        ->constrained('users')

        ->cascadeOnDelete();



    $table->decimal('amount', 12, 2);

    $table->string('status');



    $table->timestamps();

});

در اینجا:


$table->foreignId('user_id')

ستون Foreign Key را ایجاد می‌کند.

و:


->constrained('users')

مشخص می‌کند که این کلید خارجی به جدول users مربوط است.


# cascadeOnDelete چیست؟

در مثال بالا از این عبارت استفاده کردیم:


->cascadeOnDelete()

یعنی اگر یک User حذف شود، رکوردهای مرتبط او در جدول orders نیز حذف شوند.

مثلاً:


User #1

 ├── Order #1

 ├── Order #2

 └── Order #3

اگر User شماره ۱ حذف شود، با تنظیم Cascade، سفارش‌های مرتبط نیز حذف می‌شوند.

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

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


# تعریف One to Many در Model

حالا باید رابطه را در Modelهای Laravel تعریف کنیم.

فرض کنیم دو Model داریم:


app/Models/User.php

app/Models/Order.php

در Model User رابطه را با hasMany() تعریف می‌کنیم.

رابطه در Model User


public function orders()

{

    return $this->hasMany(Order::class);

}

یعنی:

> هر User می‌تواند چند Order داشته باشد.

پس ساختار Model می‌تواند به شکل زیر باشد:


namespace App\Models;



use Illuminate\Database\Eloquent\Model;



class User extends Model

{

    public function orders()

    {

        return $this->hasMany(Order::class);

    }

}


# تعریف belongsTo در Model فرزند

حالا باید رابطه معکوس را در Order تعریف کنیم.


public function user()

{

    return $this->belongsTo(User::class);

}

یعنی:

> هر Order متعلق به یک User است.

Model کامل:


namespace App\Models;



use Illuminate\Database\Eloquent\Model;



class Order extends Model

{

    protected $fillable = [

        'user_id',

        'amount',

        'status',

    ];



    public function user()

    {

        return $this->belongsTo(User::class);

    }

}

بنابراین رابطه ما به این شکل است:


User

 └── hasMany()

        ↓

      Orders



Order

 └── belongsTo()

        ↓

       User


# تفاوت hasMany و belongsTo

این دو متد را باید به‌خوبی از یکدیگر تشخیص دهید.

Modelمتدمفهوم
UserhasMany()یک User چند Order دارد
OrderbelongsTo()یک Order متعلق به یک User است

مثلاً:


$user->orders

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

اما:


$order->user

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


# دریافت تمام رکوردهای مرتبط

بعد از تعریف رابطه، دریافت سفارش‌های یک کاربر بسیار ساده می‌شود.


$user = User::find(1);



$orders = $user->orders;

حالا $orders شامل سفارش‌های کاربر شماره ۱ است.

می‌توانیم آن‌ها را نمایش دهیم:


foreach ($user->orders as $order) {

    echo $order->amount;

}


# استفاده از Relationship به‌صورت Query

رابطه فقط برای دریافت داده نیست.

می‌توانیم روی رابطه Query نیز اجرا کنیم.

مثلاً:


$orders = $user->orders()

    ->where('status', 'paid')

    ->get();

در اینجا فقط سفارش‌های پرداخت‌شده کاربر دریافت می‌شوند.

یا:


$orders = $user->orders()

    ->latest()

    ->get();

برای دریافت سفارش‌ها از جدیدترین به قدیمی‌ترین.


# تفاوت orders و orders()

این موضوع برای بسیاری از افراد تازه‌کار گیج‌کننده است.

وقتی می‌نویسیم:


$user->orders

در واقع داده‌های رابطه را دریافت می‌کنیم.

اما:


$user->orders()

خود Relationship را در اختیار ما قرار می‌دهد تا بتوانیم روی آن Query اجرا کنیم.

مثلاً:


$user->orders

برای دریافت داده مناسب است.

اما:


$user->orders()

    ->where('status', 'paid')

    ->get();

برای ساخت Query مناسب است.


# ایجاد رکورد Child از طریق Relationship

یکی از قابلیت‌های مهم Eloquent این است که می‌توانیم رکورد فرزند را مستقیماً از رابطه والد ایجاد کنیم.

مثلاً:


$user->orders()->create([

    'amount' => 500000,

    'status' => 'pending',

]);

Laravel به‌صورت خودکار user_id مربوط به User را روی سفارش قرار می‌دهد.

یعنی به جای اینکه خودمان بنویسیم:


Order::create([

    'user_id' => $user->id,

    'amount' => 500000,

    'status' => 'pending',

]);

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


$user->orders()->create([

    'amount' => 500000,

    'status' => 'pending',

]);

این روش خوانایی بسیار خوبی دارد و ارتباط بین داده‌ها را نیز واضح‌تر نشان می‌دهد.


# استفاده از save برای ایجاد Child

روش دیگر استفاده از save() است:


$order = new Order();



$order->amount = 500000;

$order->status = 'pending';



$user->orders()->save($order);

در این حالت Laravel ارتباط سفارش با User را برقرار می‌کند.


# ایجاد چند رکورد با createMany

اگر بخواهیم چند سفارش ایجاد کنیم، می‌توانیم از createMany() استفاده کنیم:


$user->orders()->createMany([

    [

        'amount' => 500000,

        'status' => 'pending',

    ],

    [

        'amount' => 750000,

        'status' => 'paid',

    ],

    [

        'amount' => 900000,

        'status' => 'paid',

    ],

]);

این قابلیت زمانی کاربردی است که چند رکورد مرتبط را به‌صورت هم‌زمان ایجاد می‌کنیم.


# Mass Assignment و رابطه One to Many

اگر از create() یا createMany() استفاده می‌کنید، باید تنظیمات Mass Assignment Model را نیز در نظر بگیرید.

مثلاً:


protected $fillable = [

    'amount',

    'status',

];

در بسیاری از مواقع نیازی نیست user_id را در fillable قرار دهید، چون Relationship مقدار آن را هنگام ایجاد رکورد تنظیم می‌کند.

همیشه باید Mass Assignment را متناسب با ساختار واقعی پروژه تنظیم کنید و داده‌های ورودی کاربر را بدون اعتبارسنجی و کنترل مستقیماً وارد Model نکنید.


# دریافت User از داخل Order

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


public function user()

{

    return $this->belongsTo(User::class);

}

بنابراین:


$order = Order::find(1);



$user = $order->user;

اکنون User مربوط به این سفارش در $user قرار دارد.

مثلاً:


echo $order->user->name;

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


# Eager Loading در One to Many

یکی از موضوعات مهم هنگام کار با Relationshipها، Eager Loading است.

فرض کنید می‌خواهیم کاربران را دریافت کنیم و برای هر کاربر سفارش‌هایش را نیز نمایش دهیم.

ممکن است بنویسیم:


$users = User::all();



foreach ($users as $user) {

    foreach ($user->orders as $order) {

        // ...

    }

}

در پروژه‌های بزرگ، این روش می‌تواند باعث اجرای Queryهای متعدد شود.

برای چنین شرایطی می‌توانیم از with() استفاده کنیم:


$users = User::with('orders')->get();

در این حالت Laravel رابطه orders را به‌صورت Eager Loading بارگذاری می‌کند.

سپس:


foreach ($users as $user) {

    foreach ($user->orders as $order) {

        echo $order->amount;

    }

}


# مشکل N+1 Query چیست؟

یکی از مشکلات رایج در استفاده نادرست از Relationshipها، N+1 Query است.

فرض کنید ۱۰۰ کاربر داریم و برای هر کاربر سفارش‌ها را جداگانه دریافت کنیم.

ممکن است:


1 Query برای دریافت کاربران

+

100 Query برای دریافت سفارش‌های کاربران

در نتیجه:


101 Query

اجرا شود.

اما با:


$users = User::with('orders')->get();

Laravel داده‌های مرتبط را به شکل بهینه‌تری بارگذاری می‌کند.

به همین دلیل هنگام کار با Relationshipهای متعدد، شناخت Eager Loading اهمیت زیادی دارد.


# Lazy Loading در Laravel

وقتی رابطه را به این شکل استفاده می‌کنیم:


$user->orders

و قبلاً آن را Eager Load نکرده باشیم، Laravel می‌تواند در زمان دسترسی به Relationship آن را بارگذاری کند.

این رفتار را Lazy Loading می‌نامیم.

مثلاً:


$user = User::find(1);



$orders = $user->orders;

رابطه هنگام دسترسی به orders بارگذاری می‌شود.

Lazy Loading برای بعضی سناریوها بسیار راحت است، اما اگر در یک Loop روی تعداد زیادی Model استفاده شود، باید مراقب N+1 Query باشیم.


# شمارش رکوردهای مرتبط با withCount

گاهی فقط می‌خواهیم بدانیم هر User چند سفارش دارد و نیازی به دریافت تمام سفارش‌ها نداریم.

در این حالت withCount() بسیار کاربردی است:


$users = User::withCount('orders')->get();

حالا:


$user->orders_count

تعداد سفارش‌های کاربر را در اختیار ما قرار می‌دهد.

مثلاً:


foreach ($users as $user) {

    echo $user->name . ': ';

    echo $user->orders_count;

}

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


# فیلتر کردن Model بر اساس وجود Relationship

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

می‌توانیم از has() استفاده کنیم:


$users = User::has('orders')->get();

برای مثال اگر بخواهیم کاربرانی را پیدا کنیم که حداقل سه سفارش دارند:


$users = User::has('orders', '>=', 3)->get();

این قابلیت برای فیلتر کردن داده‌ها بر اساس Relationship بسیار مفید است.


# استفاده از whereHas

گاهی می‌خواهیم والد را بر اساس شرایطی روی Childها فیلتر کنیم.

مثلاً فقط کاربرانی را می‌خواهیم که حداقل یک سفارش پرداخت‌شده دارند:


$users = User::whereHas('orders', function ($query) {

    $query->where('status', 'paid');

})->get();

یعنی:

> کاربرانی را پیدا کن که سفارشی با وضعیت paid دارند.

این قابلیت در پروژه‌های واقعی بسیار مهم است.


# Eager Loading همراه با شرط

می‌توانیم Relationship را همراه با شرط نیز Load کنیم.

مثلاً:


$users = User::with([

    'orders' => function ($query) {

        $query->where('status', 'paid');

    }

])->get();

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


# رابطه One to Many با Category و Product

رابطه User و Order تنها یک مثال است.

یکی از مثال‌های بسیار رایج در فروشگاه‌ها:


Category

   │

   ├── Product

   ├── Product

   ├── Product

   └── Product

یک Category می‌تواند چند Product داشته باشد.

در Model Category:


public function products()

{

    return $this->hasMany(Product::class);

}

و در Model Product:


public function category()

{

    return $this->belongsTo(Category::class);

}

در دیتابیس نیز:


products

------------------

id

category_id

name

price

خواهیم داشت.


# رابطه One to Many با Post و Comment

مثال بسیار رایج دیگر:


Post

 │

 ├── Comment

 ├── Comment

 └── Comment

یک مقاله می‌تواند چند دیدگاه داشته باشد.

در Post:


public function comments()

{

    return $this->hasMany(Comment::class);

}

و در Comment:


public function post()

{

    return $this->belongsTo(Post::class);

}

حالا می‌توانیم بنویسیم:


$post->comments

یا:


$comment->post


# تغییر Foreign Key پیش‌فرض

Laravel بر اساس Convention معمولاً می‌تواند Foreign Key را به‌صورت خودکار تشخیص دهد.

برای مثال:


$this->hasMany(Order::class);

در Model User معمولاً انتظار دارد Foreign Key در جدول orders برابر با:


user_id

باشد.

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

مثلاً:


customer_id

در این صورت می‌توانیم Foreign Key را مشخص کنیم:


public function orders()

{

    return $this->hasMany(Order::class, 'customer_id');

}

در سمت فرزند نیز می‌توانیم کلید خارجی را مشخص کنیم:


public function user()

{

    return $this->belongsTo(User::class, 'customer_id');

}

بنابراین همیشه لازم نیست از نام‌های پیش‌فرض Laravel استفاده کنیم.


# تغییر Local Key

در حالت معمول Laravel رابطه را با id مدل والد برقرار می‌کند.

اما در شرایط خاص می‌توانیم Local Key را نیز مشخص کنیم.

مثلاً:


return $this->hasMany(

    Order::class,

    'customer_code',

    'code'

);

در این مثال:


orders.customer_code

        ↓

users.code

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

البته استفاده از کلیدهای سفارشی باید با طراحی صحیح دیتابیس انجام شود و بهتر است تا حد امکان Conventionهای Laravel حفظ شوند.


# ویرایش رکوردهای مرتبط

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

مثلاً:


$order = $user->orders()->find(10);



$order->update([

    'status' => 'paid',

]);

در اینجا سفارش مربوط به User را پیدا کرده و وضعیت آن را تغییر می‌دهیم.

همچنین می‌توانیم مستقیماً روی Query رابطه عملیات انجام دهیم:


$user->orders()

    ->where('status', 'pending')

    ->update([

        'status' => 'cancelled',

    ]);

در این حالت سفارش‌های Pending مربوط به همان User تغییر می‌کنند.


# حذف رکوردهای مرتبط

برای حذف یک سفارش:


$order->delete();

یا از طریق Relationship:


$user->orders()->where('id', 10)->delete();

اما باید بین دو مفهوم تفاوت قائل شویم:


حذف Child

و:


حذف Parent

اگر User را حذف کنیم، اینکه سفارش‌های او نیز حذف شوند یا باقی بمانند، به طراحی Foreign Key و قوانین کسب‌وکار سیستم بستگی دارد.


# One to Many در یک پروژه واقعی Laravel

فرض کنیم در حال ساخت فروشگاه اینترنتی هستیم.

ساختار دیتابیس:


users

 └── id



orders

 ├── id

 ├── user_id

 ├── amount

 └── status

Model کاربر:


class User extends Authenticatable

{

    public function orders()

    {

        return $this->hasMany(Order::class);

    }

}

Model سفارش:


class Order extends Model

{

    protected $fillable = [

        'amount',

        'status',

    ];



    public function user()

    {

        return $this->belongsTo(User::class);

    }

}

حالا ایجاد سفارش:


$user->orders()->create([

    'amount' => 1200000,

    'status' => 'pending',

]);

دریافت سفارش‌ها:


$orders = $user->orders;

دریافت کاربر سفارش:


$user = $order->user;

دریافت کاربران دارای سفارش:


$users = User::has('orders')->get();

دریافت تعداد سفارش‌ها:


$users = User::withCount('orders')->get();

و دریافت کاربرانی که سفارش پرداخت‌شده دارند:


$users = User::whereHas('orders', function ($query) {

    $query->where('status', 'paid');

})->get();

این مجموعه تقریباً بخش زیادی از نیازهای رایج One to Many را پوشش می‌دهد.


# اشتباهات رایج در One to Many

۱. قرار دادن Foreign Key در جدول اشتباه

در رابطه:


User → Orders

معمولاً باید:


orders.user_id

وجود داشته باشد، نه اینکه چند شناسه سفارش را داخل جدول User ذخیره کنیم.


۲. ذخیره چند ID در یک ستون

برای مثال این ساختار مناسب نیست:


users



id | order_ids

1  | 1,2,3,4

این روش برخلاف طراحی رابطه‌ای صحیح دیتابیس است.

بهتر است هر Order یک رکورد مستقل داشته باشد:


orders



id | user_id

1  | 1

2  | 1

3  | 1

4  | 1


۳. اشتباه گرفتن hasMany و belongsTo

این کد:


$user->orders()

از hasMany() استفاده می‌کند.

ولی:


$order->user()

از belongsTo() استفاده می‌کند.

اگر این دو رابطه را اشتباه تعریف کنید، Eloquent نمی‌تواند Relationship را به شکل مورد انتظار شما مدیریت کند.


۴. فراموش کردن Foreign Key

اگر جدول orders ستون:


user_id

نداشته باشد، رابطه استاندارد User و Order به شکل مورد انتظار کار نخواهد کرد.


۵. ایجاد N+1 Query

این الگو را باید با دقت استفاده کنید:


$users = User::all();



foreach ($users as $user) {

    echo $user->orders->count();

}

اگر داده‌ها زیاد باشند، بهتر است از:


User::withCount('orders')->get();

یا در صورت نیاز:


User::with('orders')->get();

استفاده کنید.


# چه زمانی از One to Many استفاده کنیم؟

هر زمان یک رکورد می‌تواند چند رکورد مرتبط داشته باشد، One to Many یکی از گزینه‌های اصلی شماست.

نمونه‌های رایج:

ParentChild
UserOrder
UserAddress
CategoryProduct
PostComment
CountryCity
CompanyEmployee
CourseLesson
BrandProduct
InvoiceInvoice Item
TicketTicket Message

البته انتخاب نوع Relationship باید بر اساس منطق واقعی داده‌ها انجام شود.


# تفاوت One to One و One to Many

در مقاله قبلی با One to One آشنا شدیم.

تفاوت اصلی این دو رابطه تعداد رکوردهای مرتبط است.

One to One


User

 │

 └── Profile

یک User یک Profile دارد.

One to Many


User

 ├── Order

 ├── Order

 └── Order

یک User چند Order دارد.

در Laravel نیز معمولاً:


hasOne()

برای One to One و:


hasMany()

برای One to Many استفاده می‌شود.


# تفاوت One to Many و Many to Many

در One to Many:


Category

   ↓

Products

هر Product معمولاً به یک Category تعلق دارد.

اما در Many to Many ممکن است:


Product

 ↔

Category

باشد؛ یعنی یک Product بتواند چند Category داشته باشد و یک Category نیز چند Product داشته باشد.

در چنین شرایطی معمولاً به یک جدول واسط یا Pivot Table نیاز داریم.

این موضوع در مقاله بعدی یعنی Many to Many در Laravel بررسی خواهد شد.


# نکات مهم برای استفاده حرفه‌ای از One to Many

برای اینکه Relationshipهای پروژه Laravel شما در پروژه‌های واقعی قابل نگهداری باشند، چند نکته را همیشه در نظر داشته باشید:

۱. از Conventionهای Laravel استفاده کنید

نام‌هایی مانند:


user_id

category_id

post_id

باعث می‌شوند Eloquent بتواند Relationshipها را راحت‌تر تشخیص دهد.

۲. Foreign Key را به‌درستی تعریف کنید

ترجیحاً Constraintهای دیتابیس را جدی بگیرید.

۳. برای داده‌های زیاد از Eager Loading استفاده کنید

مثلاً:


User::with('orders')->get();

۴. برای شمارش فقط از withCount استفاده کنید

اگر فقط تعداد را لازم دارید:


User::withCount('orders')->get();

بهتر است کل سفارش‌ها را بی‌دلیل Load نکنید.

۵. N+1 Query را جدی بگیرید

در پروژه‌های کوچک ممکن است متوجه آن نشوید، اما در پروژه‌های بزرگ می‌تواند روی عملکرد برنامه تأثیر قابل توجهی داشته باشد.

۶. حذف Cascade را با منطق کسب‌وکار هماهنگ کنید

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


# جمع‌بندی

One to Many در Laravel یکی از پرکاربردترین Relationshipهای Eloquent است و زمانی استفاده می‌شود که یک رکورد از جدول والد بتواند چند رکورد در جدول فرزند داشته باشد.

ساختار اصلی آن به این شکل است:


Parent

  │

  └── hasMany()

          ↓

        Child

و در جهت معکوس:


Child

  │

  └── belongsTo()

          ↓

        Parent

برای مثال در سیستم سفارش:


User

 ├── Order

 ├── Order

 └── Order

در Model کاربر:


public function orders()

{

    return $this->hasMany(Order::class);

}

و در Model سفارش:


public function user()

{

    return $this->belongsTo(User::class);

}

بعد از تعریف Relationship می‌توانیم به‌سادگی داده‌های مرتبط را دریافت کنیم:


$user->orders;

سفارش ایجاد کنیم:


$user->orders()->create([

    'amount' => 500000,

    'status' => 'pending',

]);

تعداد سفارش‌ها را بگیریم:


User::withCount('orders')->get();

و بر اساس Relationship فیلتر کنیم:


User::whereHas('orders', function ($query) {

    $query->where('status', 'paid');

})->get();

بنابراین یادگیری hasMany() و belongsTo() یک مرحله مهم در مسیر یادگیری Eloquent و توسعه پروژه‌های واقعی Laravel است.


# سوالات متداول

One to Many در Laravel چیست؟

One to Many رابطه‌ای است که در آن یک رکورد والد می‌تواند چند رکورد فرزند داشته باشد؛ مانند یک User که چند Order دارد.

برای One to Many در Laravel از چه متدی استفاده می‌شود؟

در Model والد معمولاً از:


hasMany()

و در Model فرزند از:


belongsTo()

استفاده می‌شود.

Foreign Key در One to Many کجا قرار می‌گیرد؟

معمولاً Foreign Key در جدول سمت Many قرار می‌گیرد. مثلاً در رابطه User و Order، ستون user_id در جدول orders قرار دارد.

چگونه سفارش‌های یک User را دریافت کنیم؟

بعد از تعریف رابطه:


$user->orders;

چگونه یک Order برای User ایجاد کنیم؟

می‌توانیم از Relationship استفاده کنیم:


$user->orders()->create([

    'amount' => 500000,

    'status' => 'pending',

]);

تفاوت hasMany و belongsTo چیست؟

hasMany() رابطه والد با چند فرزند را تعریف می‌کند و belongsTo() رابطه فرزند با والد را مشخص می‌کند.

چگونه تعداد رکوردهای مرتبط را دریافت کنیم؟

با withCount():


$users = User::withCount('orders')->get();

سپس:


$user->orders_count

در دسترس خواهد بود.

چگونه از N+1 Query جلوگیری کنیم؟

در صورت نیاز از Eager Loading استفاده کنید:


User::with('orders')->get();

یا اگر فقط تعداد رکوردها لازم است:


User::withCount('orders')->get();

نظرات (0)

نظرات پس از تأیید مدیر نمایش داده می‌شوند

هنوز نظری ثبت نشده است؛ اولین نفر باشید!

مقالات مرتبط

ساخت CMS با Laravel 12؛ آموزش ساخت سیستم مدیریت محتوا از صفر

ساخت CMS با Laravel 12؛ آموزش ساخت سیستم مدیریت محتوا از صفر

۲۴ دقیقه
ساخت فروشگاه اینترنتی با Laravel 12؛ آموزش پروژه‌محور از صفر تا طراحی هسته فروشگاه

ساخت فروشگاه اینترنتی با Laravel 12؛ آموزش پروژه‌محور از صفر تا طراحی هسته فروشگاه

۲۲ دقیقه
ساخت Marketplace با Laravel؛ آموزش طراحی فروشگاه چندفروشندگی

ساخت Marketplace با Laravel؛ آموزش طراحی فروشگاه چندفروشندگی

۲۲ دقیقه
مدیریت Queueهای سنگین در Laravel؛ آموزش پردازش کارهای طولانی

مدیریت Queueهای سنگین در Laravel؛ آموزش پردازش کارهای طولانی

۲۲ دقیقه