در برخی اپلیکیشنها کارهایی وجود دارد که باید به صورت دورهای در زمانبندی مناسب بر روی سرور انجام شوند. از جمله این کارها میتوان به ارسال ایمیلهای تبلیغاتی، بهینهسازی دیتابیس، پشتیبان گیری از دادههای موجود در اپلیکیشن، ایجاد گزارش ترافیک اپلیکیشن و... اشاره کرد. برای خودکارسازی این کارها وجود یک سیستم زمانبندی ضروری است. سیستم Cron Job، زمانبندی کارها در لاراول را به صورت بسیار ساده و زیبایی انجام میدهد.
برای اینکه به اهمیت زمانبندی کارها در اپلیکیشنها پی ببرید، فرض کنید، شما دارای یک اپلیکیشن برای اعلام روزانه قیمت دلار هستید و میخواهید قیمت دلار را هر روز در یک ساعت مشخص برای کاربران ویژه خود پیامک کنید. در این صورت انجام دستی این کار به صورت روزانه باعث هدر رفتن وقت و هزینه شما میشود. بنابراین وجود یک سیستم برای انجام خودکار این کارها در زمان مشخص بسیار لازم است.شما با مطالعه این مقاله میتوانید با چگونگی زمانبندی کارها در لاراول آشنا شوید و ضمن یادگیری یک تکنیک فوق العاده برای زمانبندی کارها در برنامههای لاراولی از اتلاف وقت و هزینه اضافی جلوگیری کنید.
کرون(Cron)، یک سیستم زمانبندی کار مبتنی بر تعیین زمان در سیستم عامل یونیکس/لینوکس است. این سیستم دستورات را در یک بازه زمانی از پیش تعیین شده اجرا میکند. Cron از یک فایل برای کانفیگ به نام Corn table که به عنوان جدول کرون نیز شناخته میشود، برای مدیریت فرآیند برنامهریزی کارها استفاده میکند. Corn table یا جدول کرون دارای تمامی Cronهای مرتبط به یک کار خاص است. cron job از دو قسمت، عبارت cron و یک دستور خط فرمانی که باید اجرا شود تشکیل شده است.
* * * * * command/to/run
در عبارت cron بالا، (*****) هر فیلد یک گزینه برای مشخص کردن توالی زمانبندی کار است. این گزینهها به ترتیب نمایانگر دقیقه، ساعت، روز، ماه و روزهای هفته هستند. علامت ستاره به معنی تمام مقادیر ممکن است. بنابراین دستور بالا در هر دقیقه اجرا میشود. به عنوان مثال cron job زیر در ۶:۲۰ دهم هر ماه اجرا میشود:
6 20 10 * * command/to/run
لاراول Cron Jobیک سیستم مدیریت کار داخلی در لاراول است که به برنامهها قابلیت اجرای وظایف خاصی مانند ارسال نوتیفیکیشن یا حذف کاربران غیر فعال در یک دوره زمانی مشخص را میدهد. شما برای اجرای Cron Job به سیستم عامل لینوکس در سرور خود احتیاج خواهید داشت. در ضمن، برای فهم بهتر این آموزش از قبل باید با زبان php و فریمورک لاراول آشنایی داشته باشید.
در این مقاله ما میخواهیم یک اپلیکیشن ساده لاراولی ایجاد کنیم تا زمانبندی کارها در لاراول را به شما نشان دهیم. ابتدا با استفاده از دستور زیر یک پروژه جدید ایجاد میکنیم:
composer create-project --prefer-dist laravel/laravel cron
روشهای مختلفی وجود دارد که با استفاده از آنها میتوانید کارهای زمانبندی شدهی خود را در لاراول ایجاد کنید. در ادامه به توضیح هر یک از این روشها میپردازیم تا بفهمیم هر کدام چگونه در لاراول پیاده سازی میشوند.
ایجاد یک دستور آرتیسان جدید
وارد پروژه خود شوید و دستور زیر را برای ایجاد یک کلاس آریسان جدید اجرا کنید:
php artisan make:command WordOfTheDay
دستور بالا یک فایل command جدید به نام WordOfTheDay.php در دایرکتوری app/Console/Commands ایجاد خواهد کرد و اگر فایل را باز کنید کدهای زیر را مشاهده میکنید:
<?php namespace App\Console\Commands; use Illuminate\Console\Command; class WordOfTheDay extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'command:name'; /** * The console command description. * * @var string */ protected $description = 'Command description'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { // } }
در کد بالا خط زیر حاوی نام و امضای command است
protected $signature = 'command:name';
کلمه command:name با word:day جایگزین کنید. این همان چیزی است که در زمان اجرای فرمان برای انجام دادن کار انجام می دهیم:
protected $signature = 'word:day';
همانطور که مشاهده کردید، کد بالا دارای خصوصیت(property) description است. در اینجا شما برای این ویژگی، توصیفی واقعی و دقیق از کاری که این فرمان انجام میدهد را میبینید. description در زمانی که دستور Artisan list اجرا میشود به همراه امضا نمایش داده میشود. برای مثال description فرمان را به صورت زیر تغییر دهید:
protected $description = 'Send a Daily email to all users with a word and its meaning';
هر زمانی که فرمان اجرا شود متد handle فراخوانی میشود. در این متد کد انجام یک کار خاص را قرار میدهیم. فایل WordOfTheDay.php با متد handle و دیگر تغییرات انجام شده به شکل زیر خواهد بود:
<?php namespace App\Console\Commands; use App\User; use Illuminate\Console\Command; use Illuminate\Support\Facades\Mail; class WordOfTheDay extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'word:day'; /** * The console command description. * * @var string */ protected $description = 'Send a Daily email to all users with a word and its meaning'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); }/** * Execute the console command. * * @return mixed */ public function handle() { $words = [ 'aberration' => 'a state or condition markedly different from the norm', 'convivial' => 'occupied with or fond of the pleasures of good company', 'diaphanous' => 'so thin as to transmit light', 'elegy' => 'a mournful poem; a lament for the dead', 'ostensible' => 'appearing as such but not necessarily so' ]; // Finding a random word $key = array_rand($words); $value = $words[$key]; $users = User::all(); foreach ($users as $user) { Mail::raw("{$key} -> {$value}", function ($mail) use ($user) { $mail->from('info@tutsforweb.com'); $mail->to($user->email) ->subject('Word of the Day'); }); } $this->info('Word of the Day sent to All Users'); } }
قطعه کد بالا یک کلمه تصادفی را از آرایه انتخاب کرده و آن را به ایمیل تمامی کاربران ارسال خواهد کرد
حالا که فرمان را ایجاد کردیم، باید آن را در kernel ثبت کنیم. به فایل pp/Console/Kernel.php مراجع کنید:
<?php namespace App\Console; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { /** * The Artisan commands provided by your application. * * @var array */ protected $commands = [ // ]; /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { // $schedule->command('inspire') // ->hourly(); } /** * Register the commands for the application. * * @return void */ protected function commands() { $this->load(__DIR__.'/Commands'); require base_path('routes/console.php'); }}
در این فایل کلاس فرمان ایجاد شده را در ویژگی commands ثبت کرده و فرمانها را زمانبندی میکنیم تا در زمانهای از پیش تعیین شده در متد schedule اجرا شوند. در اینجا میتوانیم تمام cron jobها در لاراول را مدیریت کنیم.
این فایل را مانند نمونه زیر تغییر دهید. در این فایل ما به سادگی کلاس WordOfTheDay
را به ویژگی commands
اضافه کردیم و آن را به صورتی زمانبندی میکنیم تا هر روز اجرا شود:
<?php namespace App\Console; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { /** * The Artisan commands provided by your application. * * @var array */ protected $commands = [ Commands\WordOfTheDay::class, ]; /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { $schedule->command('word:day') ->daily(); } /** * Register the commands for the application. * * @return void */ protected function commands() { $this->load(__DIR__.'/Commands'); require base_path('routes/console.php'); }}
در ادامه اگر فرمان php artisan list را در ترمینال اجرا کنید، خواهید دید که فرمان جدید ثبت شده است. در تصویر زیر میتوانید نام فرمان به همراه امضا و توصیف آن را مشاهده کنید:
توجه داشته باشید که تنظیمات دیتابیس با مشخصات ایمیل در فایل .env قرار دارد پس باید مطمئن شوید که تعدادی کاربر با ایمیل مشخص در دیتابیس موجود میباشد. این فرمان را در ترمینال اجرا کنید:
php artisan word:day
فرمان گفت امضا اجرا خواهد شد که در protected $signature = 'command:name' قرار گرفته است همچنین میتوانید این پیام را هم در ترمینال مشاهده کنید:
سیستم زمانبندی کارها در لاراول به شما امکان اجرای متد callback یا closure را بهصورت دورهای با استفاده از متد call میدهد. در ادامه می خواهیم آن را در متد schedule از app/Console/Kernel.php اضافه کنیم. در اینجا محتوای کلاس را با متد schedule مشاهده میکنید:
<?php namespace App\Console; use App\User; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { $schedule->call(function () { User::where('spam_count', '>', 100) ->get() ->each ->delete(); })->hourly(); } }
در کد بالا ما closure را به عنوان اولین پارامتر به متد call
اضافه کردیم و زمان اجرای کار را به صورت ساعتی تنظیم کردهایم. تا در هر ساعت اجرا شود در متد call
کاربران spam با عدد بیشتر از ۱۰۰ را حذف میکنیم.
لاراول به شما این امان را میدهد تا دستورات خط فرمان را هم زمانبندی کنید. به این ترتیب میتوانید فرمانهایی(cammandها) به سیستم عامل ویا اپلیکیشنهای خارجی صادر کنید. ما از متد exec برای اجرای یک دستور خط فرمان استفاده میکنیم. در ادامه، یک نمونهی ساده را مشاهد میکنید که به شما امکان پشتیبانی گرفتن از کدهای خود را به صورت ماهانه میدهد:
<?php namespace App\Console; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { $schedule->exec( 'cp -r ' . base_path() . " " . base_path('../backups/' . date('jY')) )->monthly(); } }
متد exec ، فرمانی که به عنوان اولین آرگومان اضافه کردیم را اجرا خواهد کرد. در کد بالا این متد پروژه لاراولی شما را در پوشهی backup کپی میکند. پس از پوشه backup ،روز و سال(نمایش به صورت عددی) قرار میگیرد. همچنین شما میتوانید Jobs های لاراول را در سیستم زمانبندی کارها به همان طریقی زمانبندی کنید که فرمان های آرتیسان و closures را زمانبندی کردیم.
در ادامه میخواهیم نگاهی عمیقتر به سیستم زمانبندی کارها در لاراول داشته باشیم.
سیستم Task Scheduler یا زمانبندی کار در لاراول دستورات خط فرمان آرتیسان، shell و یا یک callback را به صورت دورهای در یک زمان مشخص اجرا میکند. برای انجام این کار تنها کافی است از متد schedule
موجود در app/Console/Kernel.php استفاده کنیم.
protected function schedule(Schedule $schedule) { $schedule->command('word:day') ->daily(); }
قسمت schedule->command('word:day')$ جایی است که ما تعیین میکنیم کدام فرمان باید اجرا شود و ;daily()<- توالی اجرا را مشخص میکند. بازههای زمانی طولانیتر هم میتوان تعیین کرد. شما میتوانید ;daily()<- را با یکی از گزینههای لیست زیر جایگزین کنید:
جهت مشاهده لیست کامل دستورات میتوانید از مستندات وبسایت لاراول استفاده کنید.
میخواهیم Cron Jobs را طوری تنظیم کنیم تا به صورت خودکار با اجرای فرمان شروع به کار کند. برای راه اندازی سیستم زمانبندی خود، تنها باید یک Cron job را اضافه کنیم که در هر دقیقه اجرا شود. برای این کار به ترمینال سرور خود بروید و سپس در پروژه خود cd کرده و فرمان زیر را اجرا کنید:
crontab -e
این فرمان فایل Crontab سرور را باز میکند. کد زیر را در فایل قرار داده، ذخیره کرده و سپس خارج شوید.
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
فراموش نکنید که /path/to/artisan را با مسیر کامل آرتیسان اپلیکیشن لاراولی خود جایگزین کنید.
یکی از مهمترین مزایای سیستم زمانبندی کارها در لاراول این است که ما میتوانیم با خیال راحت روی ایجاد دستورات و نوشتن منطقی کدها تمرکز کنید و در همان زمان لاراول بقیه کارها را به صورت خودکار انجام میدهد.
در صورتی که تجربه استفاده از زمانبندی کارها در لاراول را دارید خوشحال میشویم تا تجربیات خود را در قسمت نظرات با دیگر مخاطبان در میان بگذارید.