با مطالعه و بررسی دقیق فصل ۱۰-۱ با تمام زوایای متدهای مورد استفاده در مدل لاراول آشنا شدید. این توابع به شما کمک میکنند که در کمترین زمان ممکن به بهترین بازدهی در خروجی گرفتن از دیتابیس خود دست پیدا کنید. حال در ادامهی مطالب فصل ۱۰-۱، در این فصل به ارائهی دقیق مبحث مدلها در لاراول پرداخته و با دقت تمام Eloqunet را موشکافی خواهیم کرد.
جهت بازیابی تمام اطلاعات موجود در دیتابیس کافیست دستور زیر را در فایل controller خود یا در Clouser Function موجود در route قرار دهید تا تمام اطلاعات موجود در جدول دیتابیس مورد نظر برای شما بازیابی شود. به فرض مثال برای جدول users میتوان به روش زیر عمل کرد:
Route::get('/users', function(){ $allContacts= Contact::all(); return view('users.index', $allContacts); }
با استفاده از دستور فوق تمام اطلاعات موجود در جدول و ستونهای contacts به صورت یک آرایه در اختیار شما قرار میگیرد. برای دستیابی به هر فیلد آرایه کافیست عبارت زیر را بنویسید:
Route::get('/users', function(){ $allContacts= Contact::all(); $userName = $allContacts->usersname; return view('users.index', $userName); }
درصورتیکه برنامهی شما نیاز دارد تا هزاران رکورد را پردازش کند میتوانید از دستور chuck استفاده کنید. این متد اطلاعات موجود در یک مدل را که با دیتابیس سر و کار دارد به چندین تکهی کوچکتر تبدیل میکند و آن را به یک closuer جهت پردازش ارسال میکند. از مزیتهای این روش میتوان به نگهداری حافظه هنگام انجام پردازشهای طولانی اشاره کرد. این متد به صورت زیر بکار گرفته میشود:
Contact::chunk(200, function ($contacts) { foreach ($contacts as $contact) { // } });
همانطور که در مثال فوق ملاحظه کردید. اولین آرگومان این متد تعداد رکوردهاییست که در هر تکه یا chunk دریافت میشود و دومین آرگومان یک تابع Clouser است که عملیاتی را روی هر تکه chunk انجام میدهد.
کمی درباره این متد صحبت کنیم! در ابتدا با یک مثال شروع میکنیم. فرض کنید قصد دارید یک ویدیو را مشاهده کنید. ابتدا نام ویدیو را جستجو کرده و سپس به صفحهی پخشکنندهی (پلیر) ویدیو ارجاع داده خواهید شد. حال در این صفحه شما میتوانید ابتدا ویدیو را دانلود کرده و سپس در کامپیوتر یا موبایل آن را تماشا کنید که اینکار باعث میشود حجم و فضای سیستم شما اشغال شود. یا میتوانید ویدیو را به صورت آنلاین و بدون دانلود، دقیقه به دقیقه لود کرده و تماشا کنید که این حالت باعث میشود فضای حافظهی سیستم شما اشغال نشود. حال به تعریف متد Cursor میپردازیم. این متد مانند Chunk عمل میکند با این تفاوت که اطلاعات را به صورت سطر به سطر (row) از دیتابیس دریافت کرده و در لحظه پردازش میکند. یعنی در ابتدا تمام اطلاعات دیتابیس را بارگذاری نمیکند. بلکه به صورت سطر به سطر و مرحله به مرحله این پردازش را انجام میدهد. از مزیتهای استفاده از متد cursor میتوان به موارد زیر اشاره کرد:
نمونهی مشابهی برای تعریف این متد در لاراول وجود دارد که به صورت زیر است:
foreach (Flight::where('foo', 'bar')->cursor() as $flight) { // }
گاهی مواقع پیش آمده است که نیاز داریم یک رکورد خاص را از یک جدول بیرون کشیده و مورد استفاده قرار دهیم.
برای این کار میتوان از دو متد find و first بهره برد که در ذیل به آن اشاره خواهیم کرد. این متدها به جای بازگرداندن مجموعهای از مدلها تنها یک نمونهی مدل را باز میگردانند:
//اطلاعات یک مدل را متناسب با کلید اصلی آن باز میگرداند $flight = App\Flight::find(1); //اولین مقداری که پس از اعمال دستور Where // بدست میاید را به نمایش میگذارد $flight = App\Flight::where('active', 1)->first();
همانطور که ملاحظه کردید در نمونهی اول، رکوردی با متد find برای id = 1 در متغییر flights ذخیره شد و در متد دوم اولین مقداری که با شرط active = 1 میباشد در متغییر flights ذخیره گردید.
همچنین میتوان متد find را برای چندین رکورد اعمال کرد. یعنی با اجرای یک دستور چندین رکورد را پیدا کنیم. این رکوردها در قالب یک کالکشن یا Collection ارائه خواهند شد:
$flights = App\Flight::find([1, 2, 3]);
برخی مواقع میخواهیم هنگام پیدا نشدن یک رکورد عملیات دیگری انجام پذیرد. این روش برای مسیرهای (routes) یا کنترلرها (controllers) بسیار مناسب است. متدهای findOrFaild و firstOrFaild به عنوان دو متد بکار گرفته میشوند که اولین نتایج کوئری را بازیابی میکنند و اگر این نتایج موجود نباشند یک عبارت از کلاس Illuminate\Database\Eloquent\ModelNotFoundException به نمایشگر ارسال میکنند! به مثال زیر توجه کنید:
$model = App\Flight::findOrFail(1); $model = App\Flight::where('legs', '>', 100)->firstOrFail();
در صورتیکه هر یک از رکوردهای فوق یافت نشد یک خطای ۴۰۴ به کاربر نمایش داده خواهد شد.
همواره بروزرسانی و آپدیت مدلها امری اساسی است. زیرا هر دیتابیس و پایگاه داده باید به طور مرتب اطلاعات را دریافت، ذخیره و بروزرسانی یا حذف کند. در این بخش به توضیح دقیق و مفصل متدهایی برای آپدیت و بروزرسانی Modelها و همچنین ارتباط این متدها با کنترلر میپردازیم.
برای ساختن یک رکورد جدید در دیتابیس ابتدا باید یک مدل را ایجاد کرده و سپس متناسب با آن صفحهی ویو و کنترلر را بسازیم. بنابراین اگر شما به مبحث کنترلرها هنوز مسلط نشدید لطفا مقالهی زیر را مطالعه بفرمایید:
پس از مطالعهی مقالهی فوق باید در جریان باشید که هر کنترلری که به صورت resource تعریف میشود دارای یک متد به نام store است که وظیفهی ذخیره اطلاعات را به عهده دارد. این متد به در بستر پروتکل HTTP و متد POST اطلاعات را از سمت کاربر به کنترلر ارسال کرده و کنترلر آن را به مدل فرستاده و در نهایت پردازش جهت ذخیرهی این اطلاعات انجام میشود. متدی که وظیفهی ذخیره این اطلاعات را به عهده دارد، متد ()save
نام دارد. این متد به صورت زیر عمل میکند:
<?php namespace App\Http\Controllers; use App\Flight; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class FlightController extends Controller { /** * Create a new flight instance. * * @param Request $request * @return Response */ public function store(Request $request) { $flight = new Flight; $flight->name = $request->name; $flight->save(); } }
در مثال فوق همانطور که ملاحظه میکنید ابتدا متد store را ایجاد کردهایم. این متد یک آرگومان با روش Dependency Injection دریافت کرده که حاوی اطلاعات ارسالی توسط کاربر است. بنابراین متغییر request$ حاوی اطلاعات کاربر میباشد. سپس در اولین خط یک نمونهی جدید از مدل را جهت ذخیرهی اطلاعات در دیتابیس ایجاد کردهایم. در نهایت فیلدی که با ستون name در دیتابیس ذخیره شده است را معادل فیلدی که با نام name در فرم ویو (view) وجود داد، قرار دادهایم. حال در انتها که عملیات انتسابها انجام شد. دستور ()save را صادر کرده تا اطلاعات در پایگاه داده به واسطهی مدل ذخیره گردد. همچنین دو ستون created_at و updated_at نیز متناسب با زمان ذخیرهسازی این رکورد در دیتابیس ذخیره خواهند شد.
بروزرسانی یک مدل نیز با دستور ()save امکانپذیر خواهد بود. اما در ابتدای کار باید رکوردی که مدنظرمان هست را از طریق دستور find یا findOrFaild و یا هر دستور دیگری فراخوانی کرده و سپس معادلسازی را انجام داده و در نهایت دستور ()save را اعمال کنیم:
$flight = App\Flight::find(1); $flight->name = 'New Flight Name'; $flight->save();
در این مثال ابتدا با استفاده از دستور find رکوردی با کلید اصلی id = 1 را بازیابی کرده و سپس مقدار ستون name آن را به new Flight Name تغییر میدهیم. در نهایت با اعمال دستور ()save اطلاعات ذخیره شده و ستون updated_at که زمان بروزرسانی را ذخیره میکند، تغییر مینماید.
بروزرسانی انبوه
لاراول امکاناتی را در اختیار ما قرار داده است که با استفاده از آن بتوانیم تمامی رکوردهای موجود در یک جدول را که از شروط مشخصی پیروی میکنند بروزرسانی کنیم. به مثال زیر توجه کنید:
App\Flight::where('active', 1) ->where('destination', 'San Diego') ->update(['delayed' => 1]);
در این مثال تمامی رکوردهایی که مقدار ستون active آنها برابر ۱ است و ستون destination آنها معادل San Diego میباشد با تغییر ستون delayed آنها به عدد ۱، آپدیت و بروزرسانی خواهند شد.
در بسیاری از فرمهایی که در اختیار کاربران قرار میگیرد همواره باید یک سری ستونهای خاص در جداول دیتابیس توسط این فرمها و کاربران آپدیت یا اضافه شوند ( از متدهایی مانند save یا create برای آپدیت و ایجاد یک رکورد استفاده میشود). اما نکتهی مهم اینجاست که همیشه و همواره برخی از ستونها به صورت خودکار پر میشوند مثلا ستون id یا ستون cotacts_id و باید از هرگونه اعمال نفوذ برای تغییر مقادیر این ستونها خودداری شود. چون بعضا مشاهده شده است که هکرها و کاربرانی که قصد تخریب یک پایگاهداده را دارند به سادگی و با ارسال چندین دستور به فرمها، فرمانهایی را برای تغییر این ستونها اعمال میکنند. حال برای جلوگیری از این موضوع در داخل هر مدل یک متغییر به نام fillable$
(به عنوان لیست سفید قابل ویرایش و اضافه کردن) و guarded$
(به عنوان لیست سیاه برای جلوگیری از ویرایش و ذخیره) وجود دارد. بنابراین ستون یا ستونهایی که در متغییر fillable$
قرار داده میشوند به عنوان ستونهایی که قابلیت ویرایش دارند معرفی خواهند شد و ستونهایی که در متغییر guarded$
ذخیره میشوند به عنوان ستونهایی که قابلیت ویرایش ندارند ارائه خواهند شد.
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Flight extends Model { /** * The attributes that are mass assignable. * * @var array */ protected $fillable = ['name', 'price']; protected $guarded = ['id','contact_id','updated_at','created_at']; }
در نظر دارید که اگر بخواهیم تمام فیلدها را اجازهی دسترسی دهیم باید متغییر gaurded$
را به صورت زیر تعریف کنیم:
/** * The attributes that aren't mass assignable. * * @var array */ protected $guarded = [];
گاهی میخواهیم به نرمافزار بگوییم که یک نمونه با مشخصات موردنظر برای من ارسال کن در غیر اینصورت آن را بساز! برای اینکار از دستور *firstOr استفاده میکنیم که به دو متد new و create تقسیم میشود. تفاوتی که بین این دو متد وجود دارد این است که: متد firstOrCreate ابتدا به دنبال ستون با مقدار مشخص میگردد و در صورتیکه آن را پیدا نکند یک نمونه ایجاد کرده و آن را داخل دیتابیس ذخیره میکند و سپس اطلاعات را باز میگرداند. در حالیکه متد firstOrNew ابتدا بررسی میکند که آیا ستون با ویژگی مشخص وجود دارد و اگر وجود نداشت یک نمونه ایجاد کرده و باز میگرداند اما آن را در دیتابیس ذخیره نمیکند. بنابراین برای ذخیرهسازی نمونهی ایجاد شده با متد firstOrNew باید از دستور save استفاده کرد. به مثال زیر توجه کنید:
// در ستونی به نام name // و با مقدار Flight 10 // ایجاد کرده و آن را درون متغییر // flight ذخیره میکند $flight = App\Flight::firstOrCreate(['name' => 'Flight 10']); // در ستونی به نام name // مقداری به نام Flight 10 // ایجاد کرده و آن را درون متغییر // flight ذخیره میکند $flight = App\Flight::firstOrNew(['name' => 'Flight 10']);
این متد دقیقا مشابه متد firstOrCreate میباشد با این تفاوت که ابتدا اقدام به آپدیت کردن یک مدل میکند و اگر آن مدل وجود نداشت ابتدا آن را ساخته و سپس عمل بروزرسانی را انجام میدهد. در صورت استفاده از این متد نیازی به اعمال دستور ()save نیست:
$flight = App\Flight::updateOrCreate( ['departure' => 'Oakland', 'destination' => 'San Diego'], ['price' => 99] );
همانطور که در جریان هستید تا به الان مباحث ساخت و بروزرسانی یک مدل را مطرح کردیم اما سوالی که اینجا مطرح هست برای حذف اطلاعات یک دیتابیس از طریق مدل باید به چه صورت عمل کرد؟
از این متد برای حذف یک نمونه از مدل (یا به عبارت دیگر، حذف یک رکورد از دیتابیس) استفاده میشود که به صورت زیر تعریف خواهد شد:
$flight = App\Flight::find(1); $flight->delete();
بنابراین در این مثال ابتدا با استفاده از دستور find رکوردی با id = 1 را انتخاب کرده و در متغییر flight$
ذخیره میکنیم سپس با اعمال متد delete آن را از دیتابیس برای همیشه حذف کردهایم.
در مثال بالا همانطور که ملاحظه کردید ابتدا یک رکورد را از دیتابیس بازیابی کردیم و پس از ذخیرهسازی آن در یک متغییر اقدام به حذف آن با متد delete کردیم. اما اگر شما primary key یک رکورد را بدانید میتوانید بدون ذخیرهسازی و بازیابی آنرا از دیتابیس خود حذف کنید. نام این متد destroy است:
App\Flight::destroy(1); App\Flight::destroy([1, 2, 3]); App\Flight::destroy(1, 2, 3);
تا به این جای کار با انواع روش حذف داده آشنا شدید اما یک روش حذف اطلاعات هست که با استفاده از دستورهای Query امکانپذیر میباشد. در مثال زیر تمام رکوردهایی که مقدار active آنها برابر ۰ است حذف میشود:
$deletedRows = App\Flight::where('active', 0)->delete();
گاهی برای شما پیش میآید که میخواهید مطالب از صفحه مدیریت وب سایت شما پس از زدن دکمهی "حذف" بهجای حذف شدن همیشگی به یک سطح آشغال یا زبالهدان انتقال کرده و یک مرحله به کاربر فرصت دهیم که در صورت تایید نهایی برای همیشه از دیتابیس حذف شود. در این صورت باید از روش Soft Deleting یا حذف نرم رکوردها استفاده کرد. برای فعالسازی این روش باید ابتدا داخل مدل خود از کلاس Illuminate\Database\Eloquent\SoftDeletes استفاده کرده و متغییر dates$
را برابر عبارت deleted_at قرار دهید. به نمونهی زیر توجه کنید:
<?php namespace App; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; class Flight extends Model { use SoftDeletes; /** * The attributes that should be mutated to dates. * * @var array */ protected $dates = ['deleted_at']; }
بسیار عالی، حال باید ستون deleted_at را در جدول دیتابیس خود ذخیره کرده تا در صورت حذف نرم هر رکورد زمان و تاریخ آن مشخص شود. بنابراین در داخل فایل migrations مورد نظر خود دستور زیر را اضافه خواهیم کرد:
Schema::table('flights', function ($table) { $table->softDeletes(); });
سپس این فایل را migrate کرده و ستون را به جدول خود اضافه کنید. بسیار عالی! کار به اتمام رسید و هم اکنون با اعمال دستور delete در کنترلر، رکورد موردنظر به سطح زباله یا زبالهدان انتقال پیدا میکند.
برای بررسی اینکه آیا یک رکورد به صورت soft Delete حذف شده است یا خیر میتوان از متد trashed به صورت زیر استفاده کرد:
if ($flight->trashed()) { // }
روشی برای بازیابی اطلاعات وجود دارد که علاوه بر رکوردهایی که به روش حذف نرم، در سطل زباله قرار دارند، تمام رکوردهای دیگر را نیز نمایش دهد. با اینکار میتوان هر آنچه درون زبالهدان و سایر رکوردها هست را دریافت کرده و به کاربر نمایش دهیم:
$flights = App\Flight::withTrashed() ->where('account_id', 1) ->get();
همچنین میتوان از کوئری پیوسته و رابطهای برای دستیابی به اطلاعات درون سطل زباله استفاده کرد:
$flight->history()->withTrashed()->get();
دستور دیگری وجود دارد که با استفاده از آن میتوان تنها و تنها اطلاعاتی که به صورت حذف نرم، در سطل زباله قرار دارند را بازیابی کرد:
$flights = App\Flight::onlyTrashed() ->where('airline_id', 1) ->get();
بازگردانی اطلاعاتی که در سطل زباله قرار دارند یا به اصطلاح restore کردن آنها با متدی تحت عنوان restore انجام میپذیرد که به صورت زیر میباشد:
$flight->restore();
همانند withTrashed میتوان متد restore را در جداول رابطهدار به صورت زیر استفاده کرد:
$flight->history()->restore();
تمام این مباحث را مطرح کردیم اما موضوعی که بسیار حائز اهمیت است حذف رکوردهاییست که در سطل زباله قرار گرفتهاند. به عبارتی دیگر میخواهیم این رکوردها را برای همیشه از پایگاه داده حذف کنیم. در اینصورت باید از متد forceDelete استفاده کرد:
// حذف یک رکورد $flight->forceDelete(); // حذف تمام رکوردهای مرتبط $flight->history()->forceDelete();
بسیار عالی! به شما همراهان گرانقدر روکسو تبریک عرض میکنیم. با استفاده از دستورهای فوق توانایی کنترل دادههای ارسالی و دریافتی را کسب کردهاید و هم اکنون میتوانید نرمافزار خود را هوشمندتر کنید. در بخش ۱۰-۳ به توضیح مفصل ساخت کوئریها در مدل اشاره خواهیم کرد. با ما همراه باشید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.