شما اینجا هستید

با درود. با یکی دیگه از فصل‌های آموزش لاراول به زبان فارسی در خدمت شما عزیزان هستیم. اگر چنانچه فصل ۱ و ۲ این مجموعه آموزشی را مطالعه نکرده‌اید همین الان از منوی بالای صفحه مسیر «آموزش طراحی سایت ->آموزش Laravel» را انتخاب کرده و از ابتدا شروع کنید. چون فرآیند نصب و معرفی لاراول در دو فصل گذشته آموزش داده‌شده است. خب بسیار عالی! وارد فصل ۳ شدیم. مباحث این فصل شامل بحث کنترلرها (Controllers) و مسیریابی یا مسیردهی (Routing) است که این دو مبحث مهم را به صورت کامل از ۰ تا ۱۰۰ توضیح خواهیم داد و تا جاییکه ممکنه سعی کرده‌ایم تمام جزئیات رآموزش دهیم.

مقدمه

بسیاری از توابع کاربردی در هر نرم‌افزار تحت وب که با فریم‌ورک نوشته می‌شود دریافت درخواست از کاربر و ارسال پاسخ است که معمولا توسط پروتکل‌های HTTP یا HTTPS صورت می‌پذیرد. این بدین معنی‌ست که طراحی مسیرهایی که کاربر وارد آن می‌شود و درخواستی برای سرور ارسال می‌کند بسیار مهم و از اصلی‌ترین و اولین مقدمه‌ی هر نرم‌افزار تحت وب است. بگونه‌ای که بدون مسیرها (Routes) نرم‌افزار شما هیچ قابلیتی نخواهد داشت. در ادامه به توضیح دقیق نحوه‌ی تعریف مسیرها و همچنین کنترل آنها توسط فریم‌ورک قدرتمند لاراول می‌پردازیم.

تعریف مسیر (Route)

در لاراول ۵.۴ مسیرها (Routes) در پوشه‌ی routes تعریف شده‌اند. البته در نسخه‌های قبلی این مسیر به صورت app/Http/routes.php بود. ساده‌ترین راه‌ برای تعریف یک مسیر انطباق یک URI‌ مانند “/” به یک Clouser‌ (بستار) است:

یک سوال: URI چیست؟
پاسخ: URI‌ به مجموعه‌ی URLها و URN ها گفته می‌شود. برای روشن‌تر شدن این موضوع یک مثال خیلی مشخص می‌زنیم:

تعریف URI:‌ هر آدرسی که منبع مشخصی نداشته باشد. (مثل آدرس درایو‌ها در ویندوز و …) به نمونه‌ی زیر توجه کنید:

Files/main/page.html 

تعریف URL:‌ هر آدرسی که دارای منابع باشند مانند منبع http, https و ftp و … . (مثل آدرس وب سایت‌ها و …) به نمونه‌ی زیر توجه کنید:

http://www.puyapardaz.ir/laravel/page.html

تعریف URN:‌ هر آدرسی که منبع آن یک نام باشد. (مثل بارکد کتاب‌ها و …) به نمونه‌ی زیر توجه کنید:

ISBN 1-2345-678-9

نکته قابل توجه:‌ هر URL می‌تواند یک URI‌ باشد و هر URN نیز مجددا می‌تواند یک URI‌ باشد ولی هیچگاه یک URL‌ نمی‌تواند یک URN باشد یا بالعکس.

یک سوال: Clouser چیست؟
پاسخ: توابعی هستند که عنوان شیء، پارامتر و متغییر به سایر توابع، متدها یا رویدادها ارسال می‌شوند.

حال که با تعاریف Clouser و URI آشنا شدید اولین مثال لاراولی خود را ارائه داده تا شما را با مسیردهی لاراول آشنا کنیم. بنابراین مسیر routes/web.php را باز کرده و دستورهای موجود در آن را به حالت غیرفعال (کلید میانبر /+ctrl) درآورده و کدهای زیر را اضافه کنید:

Route::get("/",function(){
    return "Hello puyapardaz";
});

این دستور به سیستم مسیردهی لاراول فرمان می‌دهد که هر گاه کاربر مسیر /http://www.puyapardaz.ir را وارد کرد پیغام Hello puyapardaz را نمایش دهد. یا به اصطلاح هرگاه کاربر مسیر روت اصلی وب سایت را مشاهده کرد پیام موردنظر چاپ شود. شاید این سوال برای شما پیش بیاید که چرا بجای استفاده از Echo یا Print‌ از دستور return برای نمایش رشته‌ها استفاده کردیم. نکته قابل توجه این است که درخواست‌ها و پاسخ‌های کاربران از یک کانال به نام MiddleWare یا میان‌افزار عبور می‌کنند و سپس به کاربر بازگردانده می‌شوند. بنابراین دستور return‌ مستقیما به کاربر ارسال نمی‌شود. بلکه از فیلتر میان‌افزار یا MiddleWare می‌گذرد.

همچنبن توجه داشته باشید که در فایل web.php و یا هر فایل Route دیگری می‌توان چندصد Route‌ تعریف کرد. به مثال زیر توجه کنید:

Route::get('/', function () {
    return view('welcome');
});
 
Route::get('about', function () {
    return view('about');
});
 
Route::get('products', function () {
    return view('products');
});
 
Route::get('services', function () {
    return view('services');
});

فراخوانی استاتیک (ساکن)

اگر شما تجربه‌ی برنامه‌نویسی به زبان PHP را داشته باشید، شاید از نحوه‌ی فراخوانی استاتیک متدها (مثلا متد get) در کلاس‌ها (مثلا کلاس ::Route) حیرت‌زده باشید. ولی در حقیقت این متدها Static نیستند بلکه لاراول از مفهومی به نام Facade استفاده می‌کند. به عنوان نمونه اگر شما مثال اول را با بدون Facade بنویسید به صورت زیر خواهد بود:

$router->get('/', function(){
    return 'Hello puyapardaz';
});

یک سوال: Facade چیست؟
پاسخ: یک Interface است که وابستگی‌های خارجی یک کلاس را به حداقل رسانده و باعث خواناتر شدن کد‌ها و برنامه‌ها می‌شود.

متدهای مسیردهی (Route)

لاراول با استفاده از Facade مسیردهی (::Route) تمام متدها را به زیباترین شکل ممکن پشتیبانی می‌کند. متدها به شرح زیر می‌باشند:

  • ()Route::get : متدی برای خواندن صفحات
  • ()Route::post : متدی برای ایجاد و ذخیره اطلاعات
  • ()Route::put : متدی برای آپدیت و بروزرسانی اطلاعات
  • ()Route::delete : متدی برای حذف اطلاعات

کنترل کردن مسیردهی

همانطور که در جریان هستید شکل ظاهری استفاده از Closure ها مناسب یک وب اپلیکیشن قدرتمند نیست چون بعدها فرمان‌ها گسترش پیدا کرده و صفحه‌ی Route ما بسیار ناخوانا خواهد شد. یک راه معمول برای مسیردهی استفاده از نام کنترلر‌ها برای تعریف مسیردهی است:

 	
Route::get('/', 'WelcomController@inedx');

این عبارت و دستور در واقع درخواست را به آدرس URI‌ که معادل App\Http\Controllers\WelcomeController و در نهایت متد ()welcome ارسال می‌کند. این متد دقیقا مشابه یک Clouser در مثال‌های بالاست.

پارامترهای مسیردهی (Route)

اگر داخل URI‌ یک پارامتر وجود داشته باشد می‌توان آن را مستقیما به Clouser یا متد ارسال کرد. به مثال زیر توجه کنید:

Route::get('users/{id}/friends', function ($id) {
    //
});

همچنین می‌توان از پارامترهای پیشفرض استفاده کرد. به عنوان مثال پارامتر پیشفرض id$ در مثال فوق برابر fallbackId است:

Route::get('users/{id?}', function ($id = 'fallbackId') {
	//
});

و می‌توان از عبارات باقاعده (Regular Expression) استفاده کرد. این عبارات مانند یک شرط عمل می‌کنند بدین صورت که اگر شرط برقرار باشد Route مخصوص به آن اجرا می‌شود:

Route::get('users/{id}', function ($id) {
	//
})->where('id', '[0-9]+');
 
Route::get('users/{username}', function ($username) {
	//
})->where('username', '[A-Za-z]+');
 
Route::get('posts/{id}/{slug}', function ($id, $slug) {
	//
})->where(['id' => '[0-9]+', 'slug' => '[A-Za-z]+']);

برای خروجی فوق اگر کاربر آدرس users/abc را وارد کند route دوم اجرا خواهد شد و اگر عبارت posts/abc/123 در مرورگر وارد شود Route اول اجرا خواهد شد.

اسامی مسیرها (Route)

در حالت پیش‌فرض می‌توان با استفاده از تابع ()url‌ هر جای نرم‌افزار خود از مسیردهی ها استفاده کنید. به عنوان مثال:

<a href="<?php echo url('/'); ?>">

اما لاراول برای شما امکانی را فراهم کرده است که برای هر Route‌ یا مسیر خود یک نام دلخواه انتخاب کرده تا در صورت لزوم مسیرهای پیچیده را با نام اختصاری آنها معرفی کنید. به مثال زیر توجه کنید:

Route::get('members/{id}', [
	'as' => 'members.show',
	'uses' => 'MembersController@show'
]);
 
// فایل View
<a href="<?php echo route('members.show', ['id' => 14]); ?>">

در این مثال به برخی مفاهیم باید اشاره کرد. اولین مبحث تخصیص آرگومان دوم به شکل آرایه به متد get در سیستم مسیردهی Route است. لاراول آرگومان دوم Route را چک می‌کند و اگر Clouser بود آن را به صورت هوشمند اجرا می‌کند یا اگر رشته باشد آن را به عنوان یک معرف کنترل و متدهای همراه آن، می‌شناسد یا در صورت وجود یک آرایه (مانند مثال فوق) لاراول انتظار دریافت پارامترهایی دارد تا بتواند روی سیستم مسیردهی اعمال کند. پس در زیر به صورت خلاصه و تیتروار انواع پارامترهایی که به عنوان آرگومان دوم به Route و متدهای مرتبط به آن ارسال می‌شوند را بررسی می‌کنیم:

  1. Clouser، که در لحظه اجرا می‌شود
  2. String یا رشته، به کنترلر مربوطه و متد آن اشاره می‌کند
  3. Array‌ یا آرایه، تنظیمات روتر را درنظر می‌گیرد و سپس به کنترلر موردنظر و متد آن اشاره می‌کند

همانطور که در مثال فوق مشاهده می‌کنید یک نام مستعار برای این مسیردهی (route) تحت عنوان members.show اختصاص داده شده است. که این نام‌گذاری از یک قاعده و قانون کلی تبعیت می‌کند که توسط لاراول ایجاد شده است. این قانون بدین صورت است: resourcePlural.action، یعنی قسمت اول نام کنترلر به صورت جمع و camel-case است و قسمت دوم نام اکشن یا متد.

بنابراین با استفاده از ویژگی (Property)تحت عنوان “as” نام این روت (route) یا مسیر را “members.show” قرار داده ایم. سپس با استفاده از ویژگی “uses” نام کنترلر مربوطه را به این مسیر معرفی کرده‌ایم.

در نظر داریم که اختصاص نام مستعار مسیر برای یک Coluser امکان‌پذیر است. به مثال زیر توجه کنید:

Route::get('/members/{id}/edit', [
	'as' => 'members.edit',
	function ($id) {
		//
	}
]);

بسیار عالی! حال به معرفی توابع موردنیاز برای لینک دادن به این مسیرها، اشاره می‌کنیم. این توابع معمولا در view مورد استفاده قرار می‌گیرد:

()url

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

()route

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

یک مثال جامع برای مبحث پارامترهای Route ارائه می‌دهیم تا این مبحث رو به اتمام برسانیم:

درنظر بگیرید که شما آدرسی به صورت زیر دارید:

users/{userId}/comments/{commentId}

حال می‌خواهیم برای userId=1 و commentsId=2، انواع پارامترها را به همراه کاربرد آنها در View‌ نمایش دهیم:

Route::get('users/{userId'}/comments/{commentId}, [
    'as' => 'users.comments.show',
    'uses' => 'UsersCommentsController'
]);
===================================
حالت ۱:
    route('users.comments.show', [1, 2])
    خروجی: // http://www.puyapardaz.ir/users/1/comments/2
===================================
حالت ۲:
    route('users.comments.show', ['userId' => 1, 'commentId' => 2])
    خروجی: // http://www.puyapardaz.ir/users/1/comments/2
===================================
حالت ۳:
    route('users.comments.show', ['commentId' => 2, 'userId' => 1])
    خروجی: // http://www.puyapardaz.ir/users/1/comments/2
===================================
حالت ۴:
    route('users.comments.show', ['userId' => 1, 'commentId' => 2, 'opt' => 'a'])
    خروجی: // http://www.puyapardaz.ir/users/1/comments/2?opt=a

گروه‌‌بندی مسیرها (Route Groups)

گروه‌بندی مسیرها یکی از امکانات فوق‌العاده‌ای‌ست که لاراول در اختیار شما قرار می‌دهد تا از تکرار یک سری پسوند و فضای نام‌ها (namespace) خودداری نمایید. همچنین از این گروه‌بندی‌ها برای اعمال برخی کامپوننت‌های امنیتی و تایید هویت کاربری (authentication) بر روی یک دسته مسیر (routes) استفاده می‌شود. این امر از تکرار بسیاری از route ها جلوگیری می‌کند و مسیردهی اپلیکیشن شما را بسیار منظم و مرتب می‌کند.

برای تعریف کردن یک یا چندین گروه باید از متد group به صورت زیر استفاده کنید:

Route::group([], function () {
	Route::get('hello', function () {
		return 'Hello';
	});
	Route::get('world', function () {
		return 'World';
	});
});

مثال بالا هیچ فرقی با حالت route عادی ندارد. زیرا مقدار آرگومان اول group‌ نباید هرگز خالی باشد.

گروه‌بندی با استفاده از Middleware

همانطور که قبلا اشاره کردیم، میان‌افزارها (Middleware) را می‌توان به عنوان یک فیلتر و با استفاده از عبارت group یا Route::middleware به مسیردهی خود اضافه کنیم. به مثال زیر توجه کنید:

Route::group(['middleware' => 'auth'], function () {
	Route::get('dashboard', function () {
		return view('dashboard');
	});
	Route::get('account', function () {
		return view('account');
	});
});

در این مثال میان‌افزار تایید هویت (authentication) به مسیرهای http://www.puyapardaz.ir/dashboard و http://www.puyapardaz.ir/account‌ اعمال شده است که باعث می‌شود کاربر بدون ورود و عضویت نتواند وارد بخش‌های داشبورد و اکانت شود.

گروه‌بندی با استفاده از پسوندها

گاهی نیاز داریم که برای نرم‌افزار خود یک API تولید کنیم و آن را در اختیار سایر افراد قرار دهیم در این صورت باید مسیر API‌ به صورت http://www.puyapardaz.ir/api/help باشد. حال برای اینکه مسیر api/ را مدام تکرار نکنیم از یک پسوند استفاده کرده و مسیرهای درون آن را گروه‌بندی می‌کنیم. این مفهوم را با مثال زیر شفاف‌تر توضیح می‌دهیم:

Route::group(['prefix' => 'api'], function () {
	Route::get('/', function () {
		//
	});
	Route::get('help', function () {
		//
	});
});

در این حالت همانطور که مشاهده می‌کند پسوند api/ به تمام زیر گروه‌ها اضافه می‌شود.

گروه‌بندی برای ساب دامین

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

Route::group(['domain' => 'api.puyapardaz.ir'], function () {
	Route::get('/', function () {
		//
	});
});

گروه‌بندی برای فضای‌نام‌ها

برای کنترلرهایی که فضای‌نام (namespaces) مشترکی دارند می‌توان مسیردهی را گروه‌بندی کرد. در مثال زیر کنترلرهای موجود در فولدر API با فضای نام تعیین شده دیگر تکرار نخواهند شد:

// بدون اعمال کردن namespace
// App\Http\Controllers\ControllerA
Route::get('/', 'ControllerA@index');
 
// همراه با اعمال namespace
Route::group(['namespace' => 'API'], function () {
	// App\Http\Controllers\API\ControllerB
	Route::get('/', 'ControllerB@index');
});

گروه‌بندی کردن نام‌های مستعار

از این نوع گروه‌بندی برای جلوگیری از تکرار URI از نام‌های مستعار استفاده می‌کنیم. بنابراین عبارت users/comments/5 توسط یک نام مستعار مشابه users.comments.show نمایش داده خواهد شد. به مثال زیر دقت کنید:

Route::group(['as' => 'users.', 'prefix' => 'users'], function () {
	Route::group(['as' => 'comments.', 'prefix' => 'comments'], function () {
		Route::get('{id}', ['as' => 'show', function () {
			//
		}]);
	});
});
 
// در نهایت کل این مسیر در خروجی با عبارت:
//users.comments.show‌ 
// در دسترس است.

به شما تبریک می‌گوییم، با آموزش فوق شما به راحتی می‌توانید مسیردهی‌های وب اپلیکیشن خود را ایجاد کرده و در نهایت امر به تولید یک محصول کارآمد و بدون نقص بپردازید. مسیردهی (routing) به شما کمک می‌کند تا نرم‌افزاری تمیز و بدون نقص ایجاد کرده تا در صورت امکان در برهه‌ای از زمان بتوانید آن را بروزرسانی کنید و دچار سردرگمی نشوید! در جلسه‌ی آینده به توضیح مفصل کنترلرها می‌پردازیم. با ما همراه باشید.

افزودن دیدگاه جدید

دیدگاه

  • تگ‌های HTML مجاز: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd> <img>
  • خطوط و پاراگراف‌ها بطور خودکار اعمال می‌شوند.
  • نشانی صفحه‌ها وب و پست الکترونیک بصورت خودکار به پیوند تبدیل می‌شوند.

Plain text

  • تگ‌های HTML مجاز نیستند.
  • نشانی صفحه‌ها وب و پست الکترونیک بصورت خودکار به پیوند تبدیل می‌شوند.
  • خطوط و پاراگراف‌ها بطور خودکار اعمال می‌شوند.
كد امنيتي
این پرسش برای جلوگیری از ارسال اسپمهای اتوماتیک است.