بدون شک وجود eloquent یکی ازمواردی است که برنامه نویسی با لاراول را جذاب میکند. لاراول برخلاف بعضی فریمورکهای دیگر یک کتابخانه پیش فرض برای کار با دیتابیس دارد.
eloquent چیست؟
eloquent یک orm یا Object-Relation Mapper است. orm یک روش کار با دیتابیس در برنامه نویسی است که این امکان را میدهد تا با اطلاعات موجود در دیتابیس به صورت شی (object) رفتار کنیم. با این روش، کوئری زدن و انجام عملیاتهای مختلف در دیتابیس راحتتر خواهد بود.
در این سیستم هر جدول از دیتابیس یک مدل (model) خواهد داشت و ما موقع کار با جداول از این مدلها استفاده میکنیم.
در eloquent این مدل در اصل یک کلاس php است که متدها و property های مورد نیاز برای کار با جدول در آن قرار داده شده است. همه مدل ها در مسیر app/Models قرار میگیرند.
فرض کنید قرار است یک جدول داشته باشیم به نام books و داخل این جدول اطلاعات وارد کنیم، از آن اطلاعات بخوانیم و کوئری بزنیم.
اول از همه باید یک مدل برای آن ایجاد کنیم. لاراول یک دستور برای این کار دارد.
php artisan make:model Book
در این دستور اسم مدل را به شکل CamelCase مینویسیم یعنی حرف اول باید بزرگ باشد و اگر اسم مدل ما چند کلمه ای است کلمات به هم چسبیده خواهند بود و حرف اول هر کلمه بزرگ نوشته میشود.
با اجرای این دستور در مسیر app/Models یک فایل به نام Book.php ایجاد میشود:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Book extends Model
{
}
بدون استفاده از این دستور هم میتوانیم مدل را بسازیم. کافی است یک کلاس به این نام در پوشه Models ایجاد کنیم و namespace آن را هم بنویسیم. این کلاس باید کلاس Illuminate\Database\Eloquent\Model
را extend کند.
مشخص کردن اسم جدول داخل مدل
برای اینکه به eloquent بفهمانیم این مدل مربوط به کدام جدول است باید اسم جدول را داخل این کلاس مشخص کنیم به این شکل:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Book extends Model
{
protected $table="books";
}
البته اگر اسم جدول را ننویسیم به صورت پیشفرض اسم کلاس را به صورت جمع با حروف کوچک به عنوان اسم جدول در نظر میگیرد. در مثال بالا اسم کلاس Book است پس اسم پیشفرض جدول books خواهد شد. هر چند بهتر است همیشه خودمان اسم جدول را بنویسیم تا بعدا دچار مشکل نشویم.
تعیین primary key
در لاراول پیشفرض این است که primary key هر جدول یک ستون به نام id است اگر در طراحی دیتابیس شما این مورد فرق می کند اینجا میتوانید آن را بنویسید.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Book extends Model
{
protected $primarykey="book_id";
}
دریافت اطلاعات از جداول دیتابیس
تا اینجا مدل را ساختیم و مشخص کردیم که قرار است کدام جدول را نمایندگی کند. حالا میخواهیم از دل این دیتابیس اطلاعات را استخراج کنیم.
معمولا این کار را داخل controller انجام میدهیم. eloquent برای کوئری زدن یک سری متد دارد که کار را بسیار ساده میکند. در اینجا به بعضی از پرکاربردترینها اشاره میکنم. بقیه متدها را می توانید در مستندات لاراول ببینید.
گرفتن همه اطلاعات یک جدول
فرض کنید میخواهیم همه اطلاعات یک جدول را به صورت آرایه و یا آبجکت در یک متغیر دریافت کنیم و سپس روی آن عملیات انجام بدهیم. برای این از متد all استفاده میکنم:
use App\Models\Book;
$books = Book::all();
با این کار همه رکوردها در جدول books داخل متغیر به صورت آبجکت ذخیره میشوند.
بعد از این می توانید با foreach به تک تک رکوردهایی که گرفتید دسترسی داشته باشید.
foreach($books as $book){
echo $book->title;
}
چون مقداری که eloquent برمیگرداند به صورت object است. به هر attribute (یا همان ستون موجود در جدول) به صورت یک پراپرتی از آن object دسترسی داریم.
نکته: در eloquent می توانیم از method chaining استفاده کنیم یعنی اینکه چند متد را پشت سر هم بنویسیم. دقت کنید که همیشه متد اول را باید به صورت استاتیک صدا بزنیم یعنی از ::
استفاده کنیم.
دریافت یک رکورد مشخص
برای پیدا کردن یک رکورد مشخص با استفاده از id از متد find استفاده میکنیم.
use App\Models\Book;
$book = Book::find(10);
اگر با استفاده از یک یا چند شرط دنبال یک رکورد هستید باید از متد where و first استفاده کنید. به این شکل:
$book = Book::where("publish_year","=","2020")->first();
در مثال بالا اولین رکوردی که مقدار publish_year آن برابر با 2020 باشد را برمیگرداند.
روش استفاده از متد where
متد where سه پارامتر دریافت میکند. پارامتر اول اسم ستونی که دنبال آن هستید. پارامتر دوم عملگر مقایسه ای (= ، =! ، >، <) و پارامتر سوم مقدار آن ستون در جدول.
با توجه به مقداری که در متد where نوشتیم eloquent رکوردها را پیدا می کند. در ادامه هم با متد first مشخص میکنیم که دنبال اولین رکورد پیدا شده هستیم.
اگر پارامتر دوم یعنی عملگر مقایسهای را ننویسیم به شکل پیشفرض آن را “=” در نظر میگیرد.
ساخت کوئری
به احتمال زیاد در همه برنامهها قرار نیست همه رکوردها را دریافت کنیم. شاید نیاز به گرفتن گزارش از بخشی از جدول داشته باشیم. برای این کار باید کوئری مورد نظرمان را بسازیم.
قبلتر گفتم که eloquent این اجازه را به ما می دهد تا با method chaining یعنی نوشتن پشت سر هم متدها کوئری دلخواهمان را بسازیم. به این مثال نگاه کنید:
$books = Book::where('published',true)->orderBy('published_at','DESC')->take(20)->get();
غیر از وقتی که از متد all (دریافت همه رکوردهای یک جدول) و paginate (صفحه بندی رکوردهای دریافت شده) استفاده میکنیم، اگر میخواهیم مقادیری که eloquent پیدا کرده را بگیریم متد get را در انتهای کوئری می نویسیم.
متدها به ترتیبی که نوشتهایم استفاده میشوند. در مثال قبل اول شرط where چک میشود بعد رکوردهایی که در این شرط وجود دارند با متد orderBy مرتب می شوند، بعد از آن با متد take تعداد 20 رکورد انتخاب و در نهایت هم با get این رکوردها برگردانده میشوند.
برای آشنایی بیشتر با متدهای موجود در eloquent این صفحه را نگاهی بیاندازید.
کالکشن ها (collections)
کالکشن ها این امکان را به ما میدهند که موقع کوئری زدن بتوانیم متدهای مختلفی را اجرا کنیم ونتایج دلخواهمان را به دست بیاوریم.
collection یک ویژگی در لاراول است که کار با آرایهها را راحت تر میکند. کالکشن در واقع همان آرایه است با این تفاوت که می توان به صورت شی گرا با آن رفتار کرد و متدهای مختلفی را روی آن اجرا کرد. در لاراول میتوانیم آرایه را به کالکشن تبدیل کنیم و از متدهایی که کالکشن دارد استفاده کنیم. همه این متدها را میتوانید از این لینک در مستندات لاراول ببینید.
موقع کوئری زدن متدهای all و get مقادیر را به صورت collection بر میگردانند. به همین خاطر می توانیم از متدهایی که collection ها دارند موقع کوئری زدن استفاده کنیم.
برای نمونه اگر میانگین مقدار یک ستون در جدول را بخواهیم به دست آوریم از متدی به نام avg استفاده میکنیم.
$avrage = Book::all()->avg();
افزودن رکورد به دیتابیس با eloquent
ابتدا باید یک آبجکت جدید از model بسازیم، مقدار هر ستون را تعیین کنیم و در نهایت آن را ذخیره کنیم به این شکل:
use App\Models\Book;
class BookController extends Controller
{
public function insert(){
$book = new Book();
$book->title = "Personal MBA";
$book->author = "josh kaufman";
$book->save();
}
}
با انجام این کار یک رکورد جدید در جدول books ایجاد میشود. بعد از فراخوانی متد save، متغیر $book
یک مدل را در خود دارد. حالا اگر به عنوان مثال $book->id
را چاپ کنید به id این رکورد ساخته شده دسترسی دارید.
آپدیت کردن مدل
برای آپدیت کردن یک رکورد دیتابیس اول باید آن را دریافت کنیم، مقدار ستونی که میخواهیم را تغییر دهیم و بعد آن را ذخیره کنیم:
use App\Models\Book;
$book=Book::find(10);
$book->publish_year = "1995";
$book->save();
Mass Assignment یا تغییر دسته جمعی رکوردها در جدول
eloquent به صورت پیشفرض از مدلها جلوی تغییر جمعی چندین رکورد با هم محافظت میکند. این امکان وجود دارد که با اجرای یک متد چند رکورد را در جدول ایجاد یا آپدیت کنیم.
Book::create(
['title'=>'personal mba' ,'publish_year' => '2020'],
['title'=>'harry potter' ,'publish_year' => '2001'],
);
با متد create میتوانیم دو رکورد را یکجا ایجاد کنیم. اما در حالت عادی eloquent این اجازه را نمیدهد. برای حل این مسئله در مدل یک property به نام fillable اضافه می کنیم و اسم ستون هایی که می خواهیم به این روش ایجاد یا آپدیت کنیم را می نویسیم.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Book extends Model
{
protected $fillable=['title','publish_year'];
}
دریافت یا ایجاد مدل جدید
گاهی نیاز داریم که چک کنیم اگر یک رکورد با مشخصات مورد نظر ما در جدول وجود داشت آن را دریافت کنیم و در غیر اینصورت آن را ایجاد کنیم. در چنین موارد از متد firstOrCreate استفاده خواهیم کرد.
$book= Book::firstOrCreate(
['title' => 'Personal MBA'],
['publish_year' => 2020, 'author' => 'josh kaufman']
);
این متد دو پارامتر میگیرد اولی آرایهای است از مقادیر رکوردی که دنبال آن می گردیم و پارامتر دوم آرایهای از مقدار attribute هایی که دوست داریم در صورت نبودن این رکورد در جدول ایجاد شوند.
در مثال بالا اول چک میکند که آیا رکوردی وجود دارد که مقدار “title” آن بربر با “Personal MBA” یا خیر. اگر وجود داشت، نهایت تمام این رکورد در متغیر $book
قرار می گیرد. اگر هم چنین رکوردی نبود آن را ایجاد می کند و برمیگرداند.
آپدیت یا ایجاد مدل جدید
با استفاده از متد updateOrCreate میتوانیم یک رکورد با مشخصات مورد نظرمان را جستجو کنیم اگر وجود داشت آن را آپدیت کنیم و اگر نبود آن را ایجاد کنیم.
$book= Book::updateOrCreate(
['title' => 'Personal MBA'],
['publish_year' => 2020, 'author' => 'josh kaufman']
);
پارامتر اول آرایه ای از attribute هایی است که در جدول دنبال آن می گردیم و آرایه دوم مقدار attribute هایی است که باید آپدیت یا ایجاد شوند.
متد firstOrCreate و updateOrCreate هر دو از قاعده mass assignment تیعیت میکنند.
حذف رکورد از دیتابیس
برای این کار روی مدل یا مدلهایی که دریافت کردیم متد delete را صدا می زنیم.
use App\Models\Book;
$book=Book::find(10);
$book->delete();
از متد destroy هم میتوانیم استفاده کنیم. فقط باید id مدل هایی که می خواهیم حذف شوند را به این متد پاس بدهیم.
use App\Models\Book;
Book::destroy(1);
Book::destroy(1,5,7);
soft Delete کردن مدل ها
soft delete یعنی این که به رکوردها برچسب حذف شده بزنیم اما در دیتابیس باقی بمانند. با این کار در کوئریهایی که میزنیم محاسبه نمیشوند. این کار زمانی به درد میخورد که نمیخواهیم وقتی کاربر اطلاعات را حذف کرد واقعا حذف شوند و فقط به کاربر نمایش داده نشوند.
برای این کار باید از trait به نام softDeletes در مدل استفاده کنیم.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Book extends Model
{
use SoftDeletes;
}
ضمنا جدول ما باید یک ستون به نام deleted_at ار نوع timestamp هم داشته باشد. پس لازم است با استفاده از migration این ستون را اضافه کنیم.
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
public function up(){
Schema::table('flights', function (Blueprint $table) {
$table->softDeletes();
});
}
public function down(){
Schema::table('flights', function (Blueprint $table) {
$table->dropSoftDeletes();
});
}
از این به بعد هر بار که از متد delete روی مدلهای این جدول استفاده کنیم soft delete خواهند شد.
دسترسی به مدل های soft delete شده
با متد onlyTrashed رکوردهای soft delete شده را دریافت میکنیم.
Book::onlyTrashed()->get();
بازگرداندن متدهای soft delete شده
برای برگرداندن مدل soft delete شده از متد restore استفاده میکنیم.
$book->restore();
حذف کردن مدل به صورت دائمی
اگر soft delete را فعال کردهاید برای اینکه یک مدل را به صورت دائمی حذف کنید باید از متد forceDelete استفاده کنید.
$book->forceDelete();
جمع بندی
مهارت پیدا کردن در کار با eloquent نیاز به تمرین زیاد و کار عملی دارد اما با همین دانش پایه هم می توانیم به خیلی از نیازها در نرم افزاری که مینویسیم پاسخ دهیم.
من به مرور نکات و ترفندهایی که در eloquent به کارمان می آید به این مطلب اضافه خواهم کرد. خصوصا در مورد کار با collection ها که فکر میکنم خودش یک مطلب جدا نیاز دارد.
ممنونم که در نشر علم کمک میکنی ♥
سلام علیکم
عالیه خدا قوت