وقتی یک پروژه Laravel را شروع میکنیم، ممکن است در ابتدا بتوانیم منطق برنامه را مستقیماً داخل Route بنویسیم:
Route::get('/products', function () {
return 'Products';
});
اما با بزرگتر شدن پروژه، این روش خیلی زود باعث شلوغ شدن فایل Route و سختتر شدن مدیریت کدها میشود.
اینجاست که Controller در Laravel اهمیت پیدا میکند.
Controller محلی برای قرار دادن منطق مربوط به پردازش درخواستهای برنامه است و معمولاً بین Route و سایر بخشهای برنامه قرار میگیرد.
بهصورت ساده میتوان جریان یک درخواست را اینگونه تصور کرد:
Browser
↓
Route
↓
Controller
↓
Model / Service
↓
Database
↓
Response
در این مقاله ابتدا بررسی میکنیم Controller چیست، سپس نحوه ساخت Controller با Artisan، اتصال آن به Route، تعریف متدها، ارسال داده، دریافت پارامتر، استفاده از Model، ساخت Resource Controller و نکات مهم طراحی Controllerها را یاد میگیریم.
# Controller در Laravel چیست؟
Controller یک کلاس PHP است که برای سازماندهی منطق مربوط به درخواستهای برنامه استفاده میشود.
به جای اینکه تمام کدها را داخل Route قرار دهیم، میتوانیم آنها را به Controller منتقل کنیم.
برای مثال، به جای این:
Route::get('/products', function () {
$products = [
'Laptop',
'Phone',
'Tablet'
];
return $products;
});
میتوانیم Route را به یک Controller متصل کنیم:
Route::get('/products', [ProductController::class, 'index']);
و منطق را داخل Controller قرار دهیم:
class ProductController extends Controller
{
public function index()
{
$products = [
'Laptop',
'Phone',
'Tablet'
];
return $products;
}
}
این ساختار باعث میشود مسئولیت Route و Controller از یکدیگر جدا شود.
# چرا در Laravel از Controller استفاده میکنیم؟
استفاده از Controller چند مزیت مهم دارد.
۱. مرتب شدن Routeها
اگر تمام منطق برنامه را داخل Route بنویسیم، فایل web.php خیلی سریع شلوغ میشود.
مثلاً تصور کنید یک فروشگاه اینترنتی دارای این بخشها باشد:
- محصولات
- کاربران
- سفارشها
- پرداخت
- سبد خرید
- تخفیفها
- دستهبندیها
قرار دادن منطق تمام این بخشها داخل Route کار مناسبی نیست.
Controller اجازه میدهد هر بخش را در کلاسهای جداگانه مدیریت کنیم.
۲. تفکیک مسئولیتها
Route وظیفه مسیریابی دارد.
Controller وظیفه پردازش درخواست را بر عهده میگیرد.
Model با دادهها و پایگاه داده کار میکند.
View مسئول نمایش اطلاعات است.
این جداسازی باعث میشود ساختار پروژه قابل فهمتر باشد.
۳. استفاده مجدد از ساختار کد
Controllerها کلاس هستند و میتوانیم چندین متد مرتبط را در یک Controller قرار دهیم.
برای مثال:
ProductController
index()
create()
store()
show()
edit()
update()
destroy()
این ساختار برای پیادهسازی CRUD بسیار کاربردی است.
# Controller در کدام پوشه قرار دارد؟
Controllerهای Laravel معمولاً در مسیر زیر قرار میگیرند:
app/Http/Controllers
برای مثال:
app
└── Http
└── Controllers
├── Controller.php
├── ProductController.php
├── UserController.php
└── OrderController.php
Controllerهای مختلف میتوانند بر اساس بخشهای مختلف برنامه در این ساختار سازماندهی شوند.
# ساخت Controller در Laravel
بهترین روش برای ساخت Controller استفاده از Artisan است.
برای مثال:
php artisan make:controller ProductController
بعد از اجرای این دستور، Laravel فایل Controller را ایجاد میکند.
مسیر آن معمولاً:
app/Http/Controllers/ProductController.php
خواهد بود.
# ساختار یک Controller ساده
یک Controller ساده میتواند چنین ساختاری داشته باشد:
<?php
namespace App\Http\Controllers;
class ProductController extends Controller
{
public function index()
{
return 'Products';
}
}
در اینجا:
class ProductController extends Controller
کلاس Controller را تعریف میکند.
و:
public function index()
یک متد داخل Controller است.
# متد Controller چیست؟
هر Controller میتواند چندین متد داشته باشد.
برای مثال:
class ProductController extends Controller
{
public function index()
{
return 'Product List';
}
public function create()
{
return 'Create Product';
}
public function show()
{
return 'Product Details';
}
}
هر متد میتواند مسئول یک عملیات مشخص باشد.
مثلاً:
| متد | کاربرد |
|---|---|
index() | نمایش لیست |
create() | نمایش فرم ایجاد |
store() | ذخیره اطلاعات |
show() | نمایش یک مورد |
edit() | نمایش فرم ویرایش |
update() | بروزرسانی |
destroy() | حذف |
این نامگذاری بهخصوص در ساختارهای CRUD بسیار رایج است.
# اتصال Controller به Route
بعد از ساخت Controller باید آن را به Route متصل کنیم.
فرض کنید Controller ما:
ProductController
نام دارد.
میتوانیم بنویسیم:
use App\Http\Controllers\ProductController;
Route::get('/products', [ProductController::class, 'index']);
حالا وقتی کاربر وارد:
/products
شود، Laravel متد:
index()
را در ProductController اجرا میکند.
# Route و Controller چگونه با هم کار میکنند؟
فرض کنیم کاربر این درخواست را ارسال میکند:
GET /products
Laravel ابتدا Route مناسب را پیدا میکند:
Route::get('/products', [ProductController::class, 'index']);
سپس درخواست را به:
ProductController
و متد:
index()
ارسال میکند.
در نتیجه جریان درخواست:
GET /products
↓
Route
↓
ProductController@index
↓
Response
خواهد بود.
# دریافت پارامتر Route در Controller
در مقاله قبل درباره Route Parameter صحبت کردیم.
فرض کنید Route زیر را داریم:
Route::get('/products/{id}', [ProductController::class, 'show']);
میتوانیم مقدار id را در Controller دریافت کنیم:
public function show($id)
{
return "Product ID: {$id}";
}
اگر کاربر وارد:
/products/25
شود، مقدار:
$id
برابر با:
25
خواهد بود.
# استفاده از چند پارامتر در Controller
فرض کنید Route زیر را داریم:
Route::get(
'/users/{user}/orders/{order}',
[OrderController::class, 'show']
);
میتوانیم پارامترها را دریافت کنیم:
public function show($user, $order)
{
return "User: {$user}, Order: {$order}";
}
این روش زمانی مفید است که URL شامل چند مقدار متغیر باشد.
# بازگرداندن View از Controller
یکی از رایجترین کارهای Controller، نمایش View است.
برای مثال:
public function index()
{
return view('products.index');
}
اگر فایل View زیر وجود داشته باشد:
resources/views/products/index.blade.php
Laravel آن View را نمایش میدهد.
بنابراین جریان برنامه به شکل زیر خواهد بود:
Browser
↓
Route
↓
Controller
↓
View
↓
HTML Response
# ارسال داده از Controller به View
یکی از مهمترین کاربردهای Controller، ارسال داده به View است.
مثلاً:
public function index()
{
$products = [
'Laptop',
'Phone',
'Tablet'
];
return view('products.index', compact('products'));
}
در View میتوانیم داده را دریافت کنیم:
@foreach ($products as $product)
<p>{{ $product }}</p>
@endforeach
در نتیجه Controller وظیفه آمادهسازی داده را انجام داده و View وظیفه نمایش آن را بر عهده دارد.
# ارسال چند داده به View
میتوانیم چند متغیر را نیز به View ارسال کنیم:
public function index()
{
$products = [
'Laptop',
'Phone'
];
$title = 'Products';
return view('products.index', compact(
'products',
'title'
));
}
سپس در Blade:
<h1>{{ $title }}</h1>
@foreach ($products as $product)
<p>{{ $product }}</p>
@endforeach
# استفاده از آرایه برای ارسال داده
روش دیگر ارسال داده به View استفاده از آرایه است:
return view('products.index', [
'products' => $products,
'title' => 'Products'
]);
هر دو روش کاربرد دارند و انتخاب بین آنها به سبک کدنویسی و شرایط پروژه بستگی دارد.
# استفاده از Model در Controller
در پروژههای واقعی معمولاً دادهها از آرایههای ثابت دریافت نمیشوند.
برای مثال ممکن است محصولات در دیتابیس ذخیره شده باشند.
در این حالت Controller میتواند از Model استفاده کند:
use App\Models\Product;
public function index()
{
$products = Product::all();
return view('products.index', compact('products'));
}
جریان کار:
Route
↓
Controller
↓
Product Model
↓
Database
↓
Controller
↓
View
این یکی از رایجترین الگوهای استفاده از Controller در Laravel است.
# نمایش یک محصول
فرض کنیم میخواهیم یک محصول خاص را نمایش دهیم.
یک روش ساده:
public function show($id)
{
$product = Product::findOrFail($id);
return view('products.show', compact('product'));
}
در اینجا:
Product::findOrFail($id)
محصول موردنظر را پیدا میکند.
اگر محصول وجود نداشته باشد، Laravel پاسخ مناسب خطای Not Found را ایجاد میکند.
# Route Model Binding در Controller
Laravel میتواند پیدا کردن Model را برای ما سادهتر کند.
مثلاً:
Route::get(
'/products/{product}',
[ProductController::class, 'show']
);
و در Controller:
public function show(Product $product)
{
return view('products.show', compact('product'));
}
در این حالت Laravel میتواند پارامتر Route را به Model مربوطه متصل کند.
این قابلیت همان Route Model Binding است که در مقاله قبلی نیز با آن آشنا شدیم.
مزیت آن این است که کد Controller سادهتر و خواناتر میشود.
# Controller برای عملیات CRUD
یکی از مهمترین کاربردهای Controller، پیادهسازی CRUD است.
CRUD مخفف عملیات زیر است:
Create
Read
Update
Delete
برای یک سیستم محصولات، Controller میتواند چنین ساختاری داشته باشد:
class ProductController extends Controller
{
public function index()
{
// نمایش محصولات
}
public function create()
{
// نمایش فرم ایجاد
}
public function store()
{
// ذخیره محصول
}
public function show(Product $product)
{
// نمایش محصول
}
public function edit(Product $product)
{
// نمایش فرم ویرایش
}
public function update(Product $product)
{
// بروزرسانی محصول
}
public function destroy(Product $product)
{
// حذف محصول
}
}
این ساختار یکی از الگوهای رایج برای مدیریت Resourceها در Laravel است.
# Resource Controller چیست؟
اگر بخواهیم Controller مربوط به CRUD را بسازیم، Laravel امکان ساخت Resource Controller را در اختیارمان قرار میدهد.
مثلاً:
php artisan make:controller ProductController --resource
این دستور Controllerای ایجاد میکند که متدهای استاندارد CRUD را در اختیار دارد.
ساختار آن شامل متدهایی مانند:
index()
create()
store()
show()
edit()
update()
destroy()
خواهد بود.
این روش در پروژههایی که با Resourceهای مختلف مانند:
- محصولات
- کاربران
- سفارشها
- مقالات
- دستهبندیها
کار میکنند، بسیار کاربردی است.
# اتصال Resource Controller به Route
بعد از ساخت Resource Controller میتوانیم از Resource Route استفاده کنیم:
Route::resource('products', ProductController::class);
این Route مجموعهای از مسیرهای استاندارد CRUD را برای Controller ایجاد میکند.
در نتیجه ترکیب:
Route::resource(
'products',
ProductController::class
);
با:
ProductController
یک ساختار کامل برای مدیریت محصولات ایجاد میکند.
# دریافت Request در Controller
Controller میتواند اطلاعات Request را نیز دریافت کند.
برای مثال:
use Illuminate\Http\Request;
public function store(Request $request)
{
$name = $request->name;
return $name;
}
در اینجا Laravel شیء Request را در اختیار متد Controller قرار میدهد.
این Request میتواند شامل اطلاعاتی مانند:
- دادههای فرم
- Query String
- Headerها
- اطلاعات فایل
- اطلاعات درخواست
باشد.
# Dependency Injection در Controller
یکی از قابلیتهای مهم Laravel استفاده از Dependency Injection است.
مثلاً میتوانیم Request را مستقیماً به متد تزریق کنیم:
use Illuminate\Http\Request;
public function store(Request $request)
{
//
}
Laravel وابستگی موردنیاز را از طریق Service Container مدیریت میکند.
این قابلیت باعث میشود Controllerها بتوانند به شکل تمیزتری با سرویسها و وابستگیهای مختلف کار کنند.
# استفاده از Service در Controller
در پروژههای کوچک ممکن است Controller مستقیماً با Model کار کند.
اما در پروژههای بزرگ، منطق پیچیده کسبوکار بهتر است از Controller جدا شود.
برای مثال:
Controller
↓
ProductService
↓
Product Model
↓
Database
Controller میتواند مسئول دریافت Request و برگرداندن Response باشد، در حالی که منطق پیچیدهتر در Service قرار گیرد.
مثلاً:
class ProductController extends Controller
{
public function store(
Request $request,
ProductService $productService
) {
$product = $productService->create(
$request->all()
);
return response()->json($product);
}
}
البته اینکه دقیقاً چه زمانی Service Layer ایجاد کنیم به اندازه و پیچیدگی پروژه بستگی دارد.
در پروژههای بزرگ، این تفکیک میتواند از حجیم شدن Controllerها جلوگیری کند.
# Controller Fat چیست؟
اصطلاح Fat Controller زمانی استفاده میشود که حجم زیادی از منطق برنامه داخل Controller قرار گرفته باشد.
مثلاً:
public function store(Request $request)
{
// validation
// محاسبه قیمت
// محاسبه تخفیف
// بررسی موجودی
// ثبت سفارش
// ارسال پیامک
// ارسال ایمیل
// ثبت تراکنش
// محاسبه کمیسیون
// ...
}
اگر چنین متدی بیش از حد بزرگ شود، نگهداری و تست آن دشوار خواهد شد.
بهتر است منطق پیچیده را بر اساس نیاز پروژه به بخشهای مناسب منتقل کنیم.
مثلاً:
Controller
↓
Validation
↓
Service
↓
Model
↓
Job / Event
این ساختار میتواند خوانایی و قابلیت نگهداری پروژه را افزایش دهد.
# آیا باید برای هر Model یک Controller بسازیم؟
الزامی نیست.
اما در بسیاری از پروژههای CRUD محور، داشتن Controllerهای مشخص برای Resourceها ساختار مناسبی ایجاد میکند.
برای مثال:
ProductController
OrderController
UserController
CategoryController
PostController
هر Controller میتواند مسئول عملیات مرتبط با یک بخش مشخص باشد.
البته در پروژههای پیچیدهتر ممکن است به Controllerهای تخصصیتر نیاز داشته باشیم.
# Controllerهای تو در تو و Namespaceها
در پروژههای بزرگ ممکن است تعداد Controllerها زیاد شود.
در این شرایط میتوان آنها را در پوشههای منطقی قرار داد.
مثلاً:
app/Http/Controllers/
├── Admin/
│ ├── ProductController.php
│ ├── OrderController.php
│ └── UserController.php
│
├── Api/
│ ├── ProductController.php
│ └── OrderController.php
│
└── Frontend/
├── HomeController.php
└── ProductController.php
این ساختار باعث میشود Controllerها در پروژههای بزرگتر قابل مدیریتتر باشند.
# استفاده از Middleware در Controller
Middleware میتواند قبل از رسیدن درخواست به متدهای Controller اجرا شود.
بسته به ساختار و نسخه Laravel، میتوان Middleware را در سطح Route یا Controller مدیریت کرد.
مثلاً در Route:
Route::middleware('auth')
->group(function () {
Route::get(
'/profile',
[ProfileController::class, 'index']
);
});
در این حالت کاربر ابتدا باید شرایط Middleware را داشته باشد تا درخواست به Controller برسد.
# تفاوت Route و Controller
یکی از سوالات مهم برای افراد تازهکار این است که:
Route چه تفاوتی با Controller دارد؟
| Route | Controller |
|---|---|
| مسیر درخواست را مشخص میکند | منطق پردازش درخواست را مدیریت میکند |
معمولاً در routes قرار دارد | معمولاً در app/Http/Controllers قرار دارد |
| URL و HTTP Method را مشخص میکند | متدهای پردازش درخواست را در خود دارد |
| نقطه ورود درخواست را مشخص میکند | عملیات موردنیاز درخواست را انجام میدهد |
| بهتر است ساده باشد | میتواند شامل منطق مرتبط با درخواست باشد |
برای مثال:
Route::get(
'/products',
[ProductController::class, 'index']
);
Route میگوید:
> درخواست /products را به کجا بفرستم؟
و Controller میگوید:
> با این درخواست چه کاری انجام دهم؟
# تفاوت Controller و Model
Controller و Model نیز وظایف متفاوتی دارند.
| Controller | Model |
|---|---|
| درخواست را پردازش میکند | داده و منطق مرتبط با Model را مدیریت میکند |
| با Request کار میکند | با دادههای پایگاه داده تعامل دارد |
| Response ایجاد میکند | رکوردها را دریافت و مدیریت میکند |
| بین بخشهای مختلف جریان درخواست را مدیریت میکند | نماینده داده یا موجودیت برنامه است |
مثلاً:
$product = Product::findOrFail($id);
Model:
Product
با داده محصول کار میکند.
در حالی که:
public function show($id)
{
...
}
متد Controller وظیفه پردازش درخواست نمایش محصول را دارد.
# بهترین روش برای طراحی Controller در Laravel
برای اینکه Controllerهای پروژه قابل نگهداری باشند، چند نکته مهم را رعایت کنید.
۱. Controller را بیش از حد بزرگ نکنید
اگر یک Controller صدها خط کد دارد، بررسی کنید آیا بخشی از منطق آن باید به Service یا بخش دیگری منتقل شود.
۲. Route را ساده نگه دارید
بهجای:
Route::get('/products', function () {
// lots of business logic
});
از Controller استفاده کنید:
Route::get(
'/products',
[ProductController::class, 'index']
);
۳. هر متد مسئولیت مشخصی داشته باشد
متدی مانند:
index()
بهتر است مسئول یک وظیفه مشخص باشد.
۴. از Resource Controller در CRUD استفاده کنید
برای Resourceهای استاندارد، این روش میتواند ساختار کد را منظمتر کند:
php artisan make:controller ProductController --resource
۵. منطق پیچیده را جدا کنید
اگر Controller بیش از حد پیچیده شد، استفاده از Service، Action، Job یا Event میتواند بر اساس نیاز پروژه مناسب باشد.
# یک مثال کامل Controller برای محصولات
فرض کنیم یک فروشگاه داریم و میخواهیم لیست محصولات را نمایش دهیم.
ابتدا Route:
use App\Http\Controllers\ProductController;
Route::get(
'/products',
[ProductController::class, 'index']
)->name('products.index');
سپس Controller:
namespace App\Http\Controllers;
use App\Models\Product;
class ProductController extends Controller
{
public function index()
{
$products = Product::query()
->latest()
->get();
return view(
'products.index',
compact('products')
);
}
}
و در نهایت View:
<h1>Products</h1>
@foreach ($products as $product)
<article>
<h2>{{ $product->name }}</h2>
<p>{{ $product->price }}</p>
</article>
@endforeach
جریان کامل:
GET /products
↓
Route
↓
ProductController@index
↓
Product Model
↓
Database
↓
products.index
↓
HTML Response
این یکی از الگوهای بسیار رایج در پروژههای Laravel است.
# چگونه بفهمیم Controller درست به Route متصل شده است؟
اگر Route کار نمیکند، یکی از اولین کارها اجرای این دستور است:
php artisan route:list
سپس بررسی کنید:
- URL درست باشد.
- HTTP Method درست باشد.
- Controller درست باشد.
- نام متد درست باشد.
- Namespace صحیح باشد.
مثلاً:
GET /products
ProductController@index
اگر این اطلاعات درست باشند، میتوان مرحله بعدی Debug را بررسی کرد.
# خطاهای رایج هنگام کار با Controller
Controller پیدا نمیشود
ممکن است Import مربوط به Controller را فراموش کرده باشید:
use App\Http\Controllers\ProductController;
نام متد اشتباه است
اگر Route به:
ProductController::class,
'index'
اشاره کند، باید متد index() در Controller وجود داشته باشد.
Controller در Namespace اشتباه قرار دارد
اگر Controller را داخل پوشه دیگری قرار داده باشید، Namespace آن نیز باید مطابق ساختار فایل باشد.
پارامتر Route و Controller هماهنگ نیست
مثلاً:
Route::get(
'/products/{id}',
[ProductController::class, 'show']
);
باید Controller نیز پارامتر موردنیاز را دریافت کند:
public function show($id)
{
//
}
Controller بیش از حد بزرگ شده است
اگر Controller شامل منطق بسیار زیادی شده، بهتر است مسئولیتها را بررسی و در صورت نیاز آنها را به Serviceها یا بخشهای مناسب منتقل کنید.
# جمعبندی
Controller در Laravel یکی از اجزای اصلی معماری برنامه است که کمک میکند منطق پردازش درخواستها از Routeها جدا شود.
در سادهترین حالت، جریان برنامه به این شکل است:
Request
↓
Route
↓
Controller
↓
Model / Service
↓
View / JSON / Response
در این مقاله یاد گرفتیم:
- Controller چیست؟
- چرا از Controller استفاده میکنیم؟
- Controller در کجا قرار دارد؟
- چگونه Controller بسازیم؟
make:controllerچیست؟- چگونه Controller را به Route متصل کنیم؟
- متد Controller چیست؟
- چگونه پارامتر Route را دریافت کنیم؟
- چگونه View را از Controller نمایش دهیم؟
- چگونه داده را به View ارسال کنیم؟
- چگونه از Model در Controller استفاده کنیم؟
- Route Model Binding چیست؟
- Resource Controller چیست؟
- چگونه CRUD را با Controller پیادهسازی کنیم؟
- Request چیست و چگونه وارد Controller میشود؟
- Dependency Injection در Controller چیست؟
- Fat Controller چیست؟
- چگونه Controllerهای بزرگ را مدیریت کنیم؟
- تفاوت Route، Controller و Model چیست؟
- خطاهای رایج Controller چیست؟
درک Controller به شما کمک میکند ساختار MVC در Laravel را بهتر بفهمید. حالا که میدانیم درخواست چگونه از Route به Controller میرسد، قدم بعدی این است که یاد بگیریم Controller چگونه خروجی HTML را به کاربر نمایش میدهد.
به همین دلیل مقاله بعدی این کلاستر:
«View در Laravel»
است.
# سوالات متداول
Controller در Laravel چیست؟
Controller یک کلاس برای سازماندهی و پردازش منطق مربوط به درخواستهای برنامه است و معمولاً بین Route و بخشهایی مانند Model، Service و View قرار میگیرد.
چگونه در Laravel Controller بسازیم؟
با Artisan:
php artisan make:controller ProductController
Controllerهای Laravel کجا قرار دارند؟
معمولاً در:
app/Http/Controllers
قرار میگیرند.
چگونه Route را به Controller متصل کنیم؟
مثلاً:
Route::get(
'/products',
[ProductController::class, 'index']
);
Resource Controller چیست؟
Controllerای است که ساختار استاندارد متدهای CRUD مانند index، create، store، show، edit، update و destroy را در اختیار قرار میدهد.
چگونه Resource Controller بسازیم؟
میتوانیم از این دستور استفاده کنیم:
php artisan make:controller ProductController --resource
آیا میتوان بدون Controller در Laravel کار کرد؟
بله. میتوان منطق ساده را مستقیماً داخل Route قرار داد؛ اما برای پروژههای واقعی و بزرگتر، استفاده از Controller باعث سازماندهی بهتر کد میشود.
آیا Controller باید تمام منطق برنامه را در خود داشته باشد؟
خیر. Controller بهتر است بیش از حد بزرگ و پیچیده نشود. منطق پیچیده کسبوکار را میتوان بر اساس معماری پروژه به Serviceها، Actionها، Jobها، Eventها یا سایر بخشهای مناسب منتقل کرد.
Controller چه تفاوتی با Route دارد؟
Route مشخص میکند درخواست به کدام بخش برنامه ارسال شود، در حالی که Controller منطق پردازش آن درخواست را مدیریت میکند.
Controller چه تفاوتی با Model دارد؟
Controller بیشتر با پردازش Request و ساخت Response سروکار دارد، در حالی که Model نماینده داده و تعامل با لایه داده برنامه است.





