سرفصل‌های آموزشی
آموزش مقدماتی لاراول
مفاهیم پایه Eloquent

مفاهیم پایه Eloquent

در قسمت قبل از متد ()get استفاده کردیم تا همه پست‌ها را از دیتابیس بخوانیم. کارهای خیلی بیشتری می‌توان با eloquent انجام داد و متدهای زیادی برای دریافت و ایجاد اطلاعات وجود دارد. در این دوره بخش‌های پایه‌ای را پوشش می‌دهیم تا در آینده و متناسب با نیاز پروژه‌ها بتوانید از بخش‌های پیچیده‌تر استفاده کنید.

اولین چیزی که بررسی می‌کنیم متد ()first است. این متد اولین رکورد موجود را در قالب یک مدل به ما بر می‌گرداند.

Route::get('/example', function () {
    $posts = Post::first();

    dd($posts);
});

تفاوت متد ()first با ()get در این است که متد get()، collection ای از مدل‌ها به ما برمی‌گرداند اما متد ()first تنها یک مدل به ما می‌دهد.

مانند متد ()first متد ()find وجود دارد که یک مدل را بر اساس id داده شده پیدا می‌کند. برای نمونه، کد زیر پستی که آیدی آن 1 است را پیدا می‌کند. خروجی متد ()find هم collection نیست و تنها یک مدل است.

Route::get('/example', function () {
    $posts = Post::find(1);

    dd($posts);

});

اگر روتی مانند /example/{id} داشته باشیم، می‌توانیم id دریافت شده از روت را به متد find بدهیم تا مدل مورد نظرمان را در دیتابیس پیدا کند.

Route::get('/example/{id}', function ($id) {
    $posts = Post::find($id);

    dd($posts);

});

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

Route::get('/example/{id}', function ($id) {
    $posts = Post::where('id', '=', $id);

    dd($posts);

});

درورودی اول این متد نام ستون مورد نظر، در ورودی دوم شیوه بررسی شرط (مساوی بودن، بزرگ تر و...) و در ورودی سوم مقداری که در دیتابیس دنبال آن می گردیم را می نویسیم. اکنون اگر این کد را اجرا کنیم، نتیجه درستی نخواهد داشت.

خروجی متد where از جنس Builder است! هنگام کار با eloquent می‌توانیم متدهای مختلفی را برای ایجاد کوئری مورد نظرمان صدا بزنیم. همه متدهایی که در اختیار ما قرار داده شده است درون کلاس Builder تعریف شده اند. هنگامی که کوئری مورد نظرمان را با این متدها نوشتیم، باید از متدهایی مانند ()get و ()first برای دریافت نتیجه استفاده کنیم. در نمونه ما، منطقی است که از ()first استفاده کنیم زیرا امکان ندارد برای کوئری‌ای که نوشتیم بیشتر از یک نتیجه وجود داشته باشد.

Route::get('/example/{id}', function ($id) {
    $posts = Post::where('id', '=', $id)->first();

    dd($posts);

});

اکنون خروجی این کوئری دقیقا مشابه زمانی است که از متد find استفاده کردیم.

متد where کاربردهای زیادی دارد. برای نمونه می‌توانیم یک پست را بر اساس عنوان آن پیدا کنیم.

Route::get('/example/{id}', function ($id) {
    $posts = Post::where('title', '=', 'Post one title')->first();

    dd($posts);

});

همچنین علاوه بر = می‌توانیم از عملگرهای دیگر مانند >، <، >= و... استفاده کنیم. برای نمونه می‌توانیم پست‌هایی که آیدی آن‌ها از یک بیشتر است را از دیتابیس دریافت کنیم.

Route::get('/example/{id}', function ($id) {
    $posts = Post::where('id', '>', 1)->get();

    dd($posts);

});

برای دریافت نتیجه در کوئری بالا، از متد ()get استفاده کردیم زیرا کوئری ما می‌تواند بیش از یک نتیجه داشته باشد.

با توجه به کوئری‌ای که می‌خواهیم در دیتابیس اجرا شود، می‌توانیم متد ای مختلف را پشت سر هم صدا بزنیم. برای نمونه اگر می‌خواستیم پست‌هایی که آیدی آنها از یک بیشتر است و عنوان خاصی دارند را دریافت کنیم، دوباره از متد where استفاده می‌کردیم:

Route::get('/example/{id}', function ($id) {
    $posts = Post::where('id', '>', 1)->where('title', '=', 'sokanacademy')->get();

    dd($posts);

});

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

پارامتر id را از روت /example/{id} مان حذف می‌کنیم زیرا دیگر به آن نیاز نداریم. 

برای ایجاد یک رکورد در دیتابیس، از متد ()create استفاده می‌کنیم.

Route::get('/example/', function () {
    $posts = Post::create();

    dd($posts);

});

اگر این کد را اجرا کنیم با خطای زیر مواجه می‌شویم:

در پیام این خطا گفته شده است که فیلد title مقدار پیش فرض ندارد. این یعنی ما هنگام ایجاد پست، مقدار ستون title را مشخص نکردیم. مقدار ستون‌های title و body را به صورت زیر مشخص می‌کنیم.

Route::get('/example/', function () {
    $posts = Post::create([
        'title' => 'New post',
        'body' => 'Post body'
    ]);

    dd($posts);

});

با اجرای این کد باز هم خطا دریافت می‌کنیم!

پیام این خطا به ما می‌گوید که باید title را به لیست ستون‌های fillable اضافه کنیم تا بتوانیم از قابلیت mass assignment استفاده کنیم.

قابلیت mass assignment یک محافظ ایمنی برای برنامه ما است. با وجود این قابلیت، تنها فیلدهایی از پایگاه داده ما قابل مقداردهی‌اند که خودمان مشخص می‌کنیم. اگر این قابلیت وجود نداشت و ما می‌توانستیم هر فیلدی که در دیتابیس وجود دارد را مقداردهی کنیم، ممکن بود به صورت تصادفی به کاربران برنامه‌مان اجازه انجام کارهای مخرب را بدهیم. برای نمونه ممکن است کاربرهای برنامه بتوانند مقدار فیلدی با نام is_admin که برای بررسی سطح دسترسی استفاده می‌شود را تغییر دهند.

برای مشخص کردن فیلدهایی که مثدار دهی برای آنها مجاز است به مدل Post می‌رویم و property ای با نام fillable را تعریف می‌کنیم.

<?php


namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    public $table = 'posts';

    protected $fillable = [];

}

در این property، لیست ستون‌هایی که می‌توانند مقداردهی شوند را می‌نویسیم.

protected $fillable = [
    'title',
    'body'

];

ممکن است این property را قبلا در مدل User دیده باشید.

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

اکنون اگر کدمان را دوباره اجرا کنیم، بدون بروز خطا، خروجی متد create را می‌بینیم.

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

در کدی که نوشتیم، خروجی متد ()create در متغیر $post ذخیره و سپس dump می‌شود.

متد ()create همان مدلی که ایجاد می‌کند را به ما برمی‌گرداند. بنابراین اگر نیاز باشد پس از ایجاد یک رکورد در دیتابیس از مدل آن استفاده کنیم، می‌توانیم از خروجی متد ()create بهره ببریم.

چه کارهای دیگری می‌توان با eloquent انجام داد؟ 

می‌توانیم یک پست را آپدیت کنیم. بیاید پستی که به تازگی ایجاد کردیم را آپدیت کنیم. برای انجام آپدیت، باید از مدل مربوط به رکورد مورد نظر استفاده کنیم. برای این کار از متد ()find استفاده می‌کنیم.

Route::get('/example/', function () {
    $post = Post::find(3);

    dd($post);

});

اکنون می‌توانیم روی مدل پست متد update را صدا بزنیم.

Route::get('/example/', function () {
    $post = Post::find(3);

    $post->update();

    dd($post);

});

آپدیت کردن هم مانند ایجاد یک رکورد است. تنها ستون‌هایی که می‌خواهیم مقدار آنها عوض شود را به صورت آرایه می‌نویسیم.

Route::get('/example/', function () {
    $post = Post::find(3);

    $post->update([
        'body' => 'updated body'
    ]);

    dd($post);

});

بعد از اجرای این کد، اگر به جدول posts بروید مشاهده می‌کنید که رکورد مورد نظر آپدیت شده است. همچنین اگر به مقدار ستون updated_at دقت کنید می‌بینید که این مقدار به زمان اکنون تغییر کرده است. این ستون همیشه زمان آخرین آپدیت را نگه می‌دارد.

یک کار دیگر که می‌توان با eloquent انجام داد حذف رکوردها است. برای این کار کافی است در کدی که نوشتیم، متد ()update را به ()delete تبدیل کنیم.

Route::get('/example/', function () {
    $post = Post::find(3);

    $post->delete();

    dd($post);

});

کد بالا را می‌توان بدون دریافت مدل از دیتابیس و استفاده از متد ()find هم نوشت. برای این کار می‌توانیم از متد where استفاده کنیم.

Route::get('/example/', function () {
    $post = Post::where('id', '=', 3);
    
    dd($post->delete());

});

اما به طور معمول ابتدا رکورد مورد نظر را از پایگاه داده می‌خوانیم و سپس آن را حذف یا بروزرسانی می‌کنیم. خروجی متد delete یک عدد است که به ما نشان می‌دهد چه تعداد رکورد در پایگاه داده حذف شده‌اند.

online-support-icon