وقتی یک پروژه PHP کوچک است، ممکن است بتوانید کدهای مربوط به HTML، منطق برنامه، Queryهای دیتابیس و پردازش درخواستها را در چند فایل قرار دهید و همچنان پروژه قابل مدیریت باشد.
اما با بزرگتر شدن پروژه، این روش خیلی سریع مشکلساز میشود.
فرض کنید یک فایل PHP همزمان مسئول دریافت درخواست کاربر، اتصال به دیتابیس، اجرای Query، پردازش اطلاعات، اعتبارسنجی دادهها و تولید HTML باشد. در چنین شرایطی، تغییر یک بخش میتواند روی بخشهای دیگر تأثیر بگذارد و نگهداری پروژه را دشوار کند.
اینجاست که معماری MVC اهمیت پیدا میکند.
MVC یکی از رایجترین روشها برای جدا کردن مسئولیتهای مختلف یک برنامه وب است و در بسیاری از فریمورکهای PHP، از جمله Laravel، با مفاهیم مشابه آن روبهرو میشویم.
MVC چیست؟
MVC مخفف سه بخش زیر است:
- Model
- View
- Controller
هرکدام از این بخشها مسئولیت متفاوتی در برنامه دارند:
| بخش | وظیفه |
|---|---|
| Model | مدیریت دادهها و منطق مرتبط با داده |
| View | نمایش اطلاعات به کاربر |
| Controller | مدیریت درخواست و هماهنگی بین بخشهای مختلف |
به زبان ساده، MVC تلاش میکند قسمتهای مختلف برنامه را از یکدیگر جدا کند تا هر بخش مسئولیت مشخصی داشته باشد.
یک جریان ساده MVC را میتوان به شکل زیر تصور کرد:
User
↓
Controller
↓
Model
↓
Database
↓
Model
↓
Controller
↓
View
↓
User
جزئیات این جریان ممکن است بسته به نوع پیادهسازی متفاوت باشد، اما مفهوم اصلی همان جداسازی مسئولیتهاست.
چرا از MVC استفاده میکنیم؟
فرض کنید قصد دارید صفحه لیست محصولات یک فروشگاه اینترنتی را با PHP ایجاد کنید.
در یک پروژه ساده ممکن است فایل products.php همزمان Query دیتابیس را اجرا کند و HTML را نیز تولید کند:
<?php
$pdo = new PDO(
'mysql:host=localhost;dbname=shop',
'root',
''
);
$stmt = $pdo->query("SELECT * FROM products");
$products = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html>
<head>
<title>Products</title>
</head>
<body>
<h1>Products</h1>
<?php foreach ($products as $product): ?>
<div>
<h2><?= htmlspecialchars($product['name']) ?></h2>
<p><?= htmlspecialchars($product['description']) ?></p>
<strong><?= htmlspecialchars($product['price']) ?> تومان</strong>
</div>
<?php endforeach; ?>
</body>
</html>
این کد برای یک پروژه کوچک قابل استفاده است، اما با افزایش امکانات پروژه، فایلها میتوانند بسیار پیچیده شوند.
مثلاً یک سیستم فروشگاهی ممکن است شامل موارد زیر باشد:
- کاربران
- محصولات
- دستهبندیها
- سفارشها
- پرداخت
- تخفیف
- احراز هویت
- ارسال ایمیل
- API
- پنل مدیریت
- گزارشها
اگر همه این مسئولیتها در فایلهای PHP پراکنده و درهم قرار بگیرند، نگهداری و توسعه پروژه دشوار خواهد شد.
MVC با جدا کردن مسئولیتها تلاش میکند این مشکل را کاهش دهد.
# اجزای اصلی MVC
Model چیست؟
Model بخشی از برنامه است که مسئول مدیریت دادهها و منطق مرتبط با آنهاست.
برای مثال در یک فروشگاه اینترنتی ممکن است Modelهای مختلفی داشته باشیم:
Product
User
Order
Category
Payment
برای مثال یک Model مربوط به محصولات میتواند چنین ساختاری داشته باشد:
class Product
{
public function getAll(): array
{
// دریافت محصولات از دیتابیس
}
}
در یک معماری کاملتر، Model میتواند مسئول عملیات مرتبط با دادههای یک موجودیت باشد.
برای مثال:
class Product
{
public function find(int $id): ?array
{
// دریافت یک محصول
}
public function getAll(): array
{
// دریافت تمام محصولات
}
public function create(array $data): int
{
// ایجاد محصول
}
public function update(int $id, array $data): bool
{
// بروزرسانی محصول
}
public function delete(int $id): bool
{
// حذف محصول
}
}
البته در پروژههای حرفهای ممکن است مسئولیتهای دیتابیس، Repository، Service و سایر لایهها نیز از Model جدا شوند.
View چیست؟
View مسئول نمایش اطلاعات به کاربر است.
برای مثال:
<h1>محصولات</h1>
<?php foreach ($products as $product): ?>
<div>
<h2>
<?= htmlspecialchars($product['name']) ?>
</h2>
<p>
<?= htmlspecialchars($product['description']) ?>
</p>
<strong>
<?= htmlspecialchars($product['price']) ?>
تومان
</strong>
</div>
<?php endforeach; ?>
View بهتر است روی نمایش اطلاعات تمرکز داشته باشد.
بهتر است Query دیتابیس و منطق پیچیده کسبوکار را داخل View قرار ندهیم.
Controller چیست؟
Controller مسئول مدیریت درخواست و هماهنگی بین بخشهای مختلف برنامه است.
برای مثال:
class ProductController
{
public function index()
{
$productModel = new Product();
$products = $productModel->getAll();
require __DIR__ . '/../Views/products/index.php';
}
}
در این مثال Controller:
- Model مربوط به محصولات را در اختیار میگیرد.
- محصولات را دریافت میکند.
- اطلاعات را به View ارسال میکند.
- View مربوط به لیست محصولات را نمایش میدهد.
# ارتباط Model، View و Controller
برای درک بهتر MVC، فرض کنید کاربر وارد URL زیر شود:
/products
یک جریان ساده میتواند به این شکل باشد:
کاربر
↓
/products
↓
Router
↓
ProductController
↓
Product Model
↓
Database
↓
Product Model
↓
ProductController
↓
products/index.php
↓
HTML
↓
کاربر
در این ساختار، هر بخش وظیفه مشخصی دارد.
Controller درخواست را مدیریت میکند، Model با دادهها کار میکند و View نتیجه را نمایش میدهد.
# آموزش ساخت یک MVC ساده با PHP
برای اینکه مفهوم MVC را بهتر درک کنیم، یک پروژه ساده با PHP ایجاد میکنیم که محصولات را از دیتابیس دریافت و نمایش دهد.
ساختار پروژه را به شکل زیر در نظر بگیرید:
php-mvc/
│
├── app/
│ ├── Controllers/
│ │ └── ProductController.php
│ │
│ ├── Models/
│ │ └── Product.php
│ │
│ └── Views/
│ └── products/
│ └── index.php
│
├── config/
│ └── database.php
│
├── routes/
│ └── web.php
│
└── public/
└── index.php
حالا هر قسمت را ایجاد میکنیم.
# مرحله اول: ایجاد اتصال به دیتابیس
ابتدا فایل زیر را ایجاد کنید:
config/database.php
کد زیر را داخل آن قرار دهید:
<?php
$host = 'localhost';
$dbname = 'shop';
$username = 'root';
$password = '';
$pdo = new PDO(
"mysql:host=$host;dbname=$dbname;charset=utf8mb4",
$username,
$password
);
$pdo->setAttribute(
PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION
);
return $pdo;
در این فایل یک اتصال PDO به دیتابیس MySQL ایجاد کردهایم.
نام دیتابیس در این مثال shop است.
# مرحله دوم: ساخت Model
حالا فایل زیر را ایجاد کنید:
app/Models/Product.php
کد:
<?php
class Product
{
private PDO $db;
public function __construct(PDO $db)
{
$this->db = $db;
}
public function getAll(): array
{
$statement = $this->db->query(
"SELECT * FROM products ORDER BY id DESC"
);
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
}
در این Model یک متد به نام getAll() داریم.
این متد محصولات را از جدول products دریافت میکند.
استفاده از PDO نیز باعث میشود بتوانیم ارتباط با دیتابیس را به شکل استانداردتری مدیریت کنیم.
# مرحله سوم: ساخت Controller
فایل زیر را ایجاد کنید:
app/Controllers/ProductController.php
کد:
<?php
class ProductController
{
private Product $product;
public function __construct(Product $product)
{
$this->product = $product;
}
public function index(): void
{
$products = $this->product->getAll();
require __DIR__ . '/../Views/products/index.php';
}
}
در اینجا Controller اطلاعات را از Model دریافت میکند و سپس View را اجرا میکند.
متد index() مسئول نمایش لیست محصولات است.
# مرحله چهارم: ساخت View
فایل زیر را ایجاد کنید:
app/Views/products/index.php
کد:
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<title>محصولات</title>
</head>
<body>
<h1>لیست محصولات</h1>
<?php foreach ($products as $product): ?>
<article>
<h2>
<?= htmlspecialchars($product['name']) ?>
</h2>
<p>
<?= htmlspecialchars($product['description']) ?>
</p>
<strong>
<?= htmlspecialchars($product['price']) ?>
تومان
</strong>
</article>
<?php endforeach; ?>
</body>
</html>
در این فایل فقط اطلاعات محصولات را نمایش میدهیم.
همچنین استفاده از htmlspecialchars() برای خروجی HTML میتواند از تفسیر مستقیم کاراکترهای خاص بهعنوان HTML جلوگیری کند.
# مرحله پنجم: ایجاد Router
برای اینکه درخواستهای مختلف را مدیریت کنیم، میتوانیم یک Router ساده ایجاد کنیم.
فایل:
routes/web.php
کد:
<?php
$routes = [
'GET /products' => [
ProductController::class,
'index'
],
];
در یک پروژه واقعی، Router میتواند امکانات بسیار بیشتری داشته باشد، اما هدف این مثال فقط درک ساختار MVC است.
# مرحله ششم: ایجاد Front Controller
فایل زیر را ایجاد کنید:
public/index.php
کد:
<?php
require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../app/Models/Product.php';
require_once __DIR__ . '/../app/Controllers/ProductController.php';
$pdo = require __DIR__ . '/../config/database.php';
$product = new Product($pdo);
$controller = new ProductController($product);
$controller->index();
در این مثال برای ساده نگه داشتن ساختار، درخواست مستقیماً به ProductController ارسال شده است.
در یک MVC کاملتر، Front Controller درخواست را دریافت میکند و Router بر اساس URL و HTTP Method، Controller و متد مناسب را پیدا میکند.
# MVC چه مشکلی را حل میکند؟
بدون معماری مشخص ممکن است پروژهای داشته باشیم که در آن یک فایل PHP همزمان مسئول موارد زیر باشد:
Database
+
Business Logic
+
HTML
+
Request Handling
+
Validation
با استفاده از MVC، این مسئولیتها بهتر تفکیک میشوند:
Controller
│
├── Model
│
└── View
در نتیجه توسعهدهنده راحتتر میتواند تشخیص دهد هر قسمت از کد باید در کجا قرار بگیرد.
# مزایای MVC در PHP
1. جداسازی مسئولیتها
هر قسمت از برنامه وظیفه مشخصی دارد.
Model روی دادهها، View روی نمایش و Controller روی مدیریت جریان درخواست تمرکز میکند.
2. نگهداری آسانتر کد
وقتی پروژه بزرگتر میشود، پیدا کردن کد مربوط به هر بخش سادهتر خواهد بود.
3. توسعه تیمی بهتر
در پروژههای تیمی، جداسازی ساختار میتواند همکاری بین توسعهدهندگان را سادهتر کند.
4. تستپذیری بهتر
جدا کردن بخشهای مختلف برنامه میتواند امکان تست مستقل قسمتهای مختلف را بهتر کند.
5. توسعهپذیری
در پروژههایی که به مرور امکانات بیشتری به آنها اضافه میشود، داشتن معماری مشخص میتواند مدیریت تغییرات را آسانتر کند.
# معایب MVC چیست؟
MVC هم برای همه پروژهها ضروری نیست.
اگر یک اسکریپت PHP فقط یک صفحه بسیار ساده داشته باشد، ایجاد Model، View، Controller، Router و سایر لایهها ممکن است پیچیدگی بیشتری نسبت به خود مسئله ایجاد کند.
بنابراین استفاده از MVC باید متناسب با اندازه و نیاز پروژه باشد.
هرچه پروژه پیچیدهتر شود و تعداد قابلیتها، دادهها و تعاملات آن افزایش پیدا کند، داشتن معماری منظم اهمیت بیشتری پیدا میکند.
# آیا PHP خودش MVC است؟
خیر.
PHP یک زبان برنامهنویسی است و MVC بخشی از خود زبان PHP نیست.
شما میتوانید معماری MVC را با PHP خام پیادهسازی کنید یا از فریمورکهایی استفاده کنید که معماری مبتنی بر MVC را در اختیار شما قرار میدهند.
به بیان ساده:
PHP
↓
زبان برنامهنویسی
MVC
↓
روش سازماندهی بخشهای برنامه
# آیا Laravel از MVC استفاده میکند؟
بله.
Laravel از ساختاری مبتنی بر MVC استفاده میکند.
برای مثال در Laravel با مفاهیمی مانند Controller، Model و View روبهرو میشویم.
ساختار معمول Controllerها در Laravel در بخش زیر قرار دارد:
app/Http/Controllers/
Modelها معمولاً در:
app/Models/
و Viewهای Blade معمولاً در:
resources/views/
قرار میگیرند.
بنابراین یادگیری MVC در PHP خام میتواند درک ساختار پروژههای Laravel را آسانتر کند.
البته Laravel فقط یک پیادهسازی ساده MVC نیست و امکانات بسیار بیشتری برای Routing، Middleware، Validation، Authentication، Queue، Database، Cache و سایر نیازهای توسعه وب ارائه میکند.
# تفاوت MVC و OOP چیست؟
MVC و OOP دو مفهوم متفاوت هستند.
OOP یا برنامهنویسی شیءگرا یک روش برای طراحی و نوشتن برنامه است.
اما MVC روشی برای سازماندهی قسمتهای مختلف یک برنامه است.
برای مثال میتوانیم یک پروژه MVC را با استفاده از کلاسها و اصول OOP پیادهسازی کنیم:
class Product
{
// Model
}
و:
class ProductController
{
// Controller
}
بنابراین:
OOP
↓
نحوه طراحی و نوشتن کد
MVC
↓
نحوه سازماندهی بخشهای مختلف برنامه
این دو مفهوم جایگزین یکدیگر نیستند و میتوانند در کنار هم استفاده شوند.
# MVC و Design Pattern چه ارتباطی دارند؟
MVC در بحث معماری نرمافزار مطرح میشود و با Design Patternهای کلاسیک دقیقاً یک مفهوم نیست.
یک پروژه میتواند معماری MVC داشته باشد و در بخشهای مختلف خود از الگوهای طراحی دیگری نیز استفاده کند.
برای مثال ممکن است در یک پروژه MVC از این موارد استفاده شود:
- Factory
- Strategy
- Repository
- Service Layer
- Observer
- Dependency Injection
بنابراین استفاده از MVC مانع استفاده از سایر الگوهای طراحی نیست.
# آیا Controller باید تمام منطق برنامه را داشته باشد؟
خیر.
یکی از اشتباهات رایج در پروژههای MVC این است که تمام منطق برنامه داخل Controller قرار داده شود.
برای مثال اگر Controller شامل صدها یا هزاران خط کد باشد، عملاً جداسازی مسئولیتها دوباره از بین میرود.
برای پروژههای بزرگتر میتوان منطق کسبوکار را به لایههای مناسب دیگری مانند Service منتقل کرد.
برای مثال:
Request
↓
Controller
↓
Service
↓
Repository / Model
↓
Database
این ساختار میتواند به مرور پروژه را قابل مدیریتتر کند.
# آیا Model باید HTML تولید کند؟
بهتر است Model مسئول تولید HTML نباشد.
Model باید روی دادهها و منطق مرتبط با آنها تمرکز کند.
برای مثال این کار مناسب Model نیست:
echo "<h1>Product</h1>";
بهتر است Model داده را آماده کند و View مسئول نمایش آن باشد.
# آیا View باید مستقیماً به دیتابیس متصل شود؟
بهتر است View مستقیماً Query دیتابیس اجرا نکند.
برای مثال بهتر است چنین ساختاری نداشته باشیم:
<?php
$products = $pdo->query(
"SELECT * FROM products"
)->fetchAll();
?>
و سپس همان فایل HTML را نمایش دهد.
در عوض بهتر است جریان به شکل زیر باشد:
Controller
↓
Model
↓
Database
Controller
↓
View
این جداسازی باعث میشود مسئولیت View مشخصتر باشد.
# MVC برای چه پروژههایی مناسب است؟
MVC میتواند برای پروژههای مختلف وب استفاده شود، از جمله:
- سایتهای داینامیک
- فروشگاه اینترنتی
- سیستم مدیریت محتوا
- پنل مدیریت
- سیستم رزرو
- سیستم تیکت
- نرمافزارهای تحت وب
- API
- SaaS
- سیستمهای سازمانی
البته انتخاب معماری باید بر اساس نیاز واقعی پروژه انجام شود.
# نکات مهم هنگام پیادهسازی MVC در PHP
صرفاً ایجاد سه پوشه با نامهای زیر:
Models
Views
Controllers
به معنی پیادهسازی صحیح MVC نیست.
مهمترین موضوع، جدا کردن مسئولیتها است.
برای مثال:
Model
→ داده و منطق مرتبط با داده
View
→ نمایش اطلاعات
Controller
→ مدیریت درخواست و هماهنگی بخشها
اگر تمام منطق کسبوکار را داخل Controller قرار دهید، پروژه به مرور به اصطلاح به یک Fat Controller تبدیل میشود.
به همین دلیل در پروژههای بزرگتر، معماری میتواند به شکل گستردهتری طراحی شود:
Controller
↓
Service
↓
Repository
↓
Model / Database
این موضوع بهخصوص زمانی اهمیت پیدا میکند که پروژه دارای قابلیتهایی مانند احراز هویت، پرداخت، سفارش، API، صف پردازش و سیستم دسترسی باشد.
# مسیر یادگیری MVC برای برنامهنویس PHP
اگر در حال یادگیری PHP هستید، پیشنهاد میشود MVC را بعد از یادگیری مفاهیم پایه و شیءگرایی دنبال کنید.
یک مسیر منطقی میتواند این باشد:
PHP
↓
Syntax
↓
Variables
↓
Data Types
↓
Conditions
↓
Loops
↓
Functions
↓
Arrays
↓
OOP
↓
Class & Object
↓
Inheritance
↓
Interface
↓
Trait
↓
Namespace
↓
Composer
↓
Autoload / PSR-4
↓
Dependency Injection
↓
SOLID
↓
MVC
↓
Design Patterns
↓
Laravel
با این مسیر، MVC دیگر فقط مجموعهای از سه پوشه Model و View و Controller نخواهد بود، بلکه میتوانید دلیل وجود هر لایه و ارتباط آن با معماری نرمافزار را بهتر درک کنید.
# سوالات متداول درباره MVC در PHP
MVC مخفف چیست؟
MVC مخفف Model، View و Controller است و روشی برای جداسازی مسئولیتهای مختلف یک برنامه وب محسوب میشود.
آیا PHP یک زبان MVC است؟
خیر. PHP یک زبان برنامهنویسی است و MVC یک معماری برای سازماندهی بخشهای مختلف برنامه است.
آیا Laravel از MVC استفاده میکند؟
بله. Laravel از ساختاری مبتنی بر MVC استفاده میکند و مفاهیمی مانند Model، View و Controller را در اختیار توسعهدهنده قرار میدهد.
تفاوت MVC و OOP چیست؟
OOP یک روش برنامهنویسی شیءگراست، در حالی که MVC روشی برای سازماندهی بخشهای مختلف یک برنامه است. یک پروژه MVC میتواند با استفاده از OOP نوشته شود.
آیا برای هر پروژه PHP باید از MVC استفاده کنیم؟
خیر. برای پروژههای بسیار کوچک ممکن است استفاده از MVC باعث پیچیدگی غیرضروری شود. اما با افزایش پیچیدگی پروژه، معماری منظم اهمیت بیشتری پیدا میکند.
آیا MVC یک Design Pattern است؟
MVC معمولاً بهعنوان یک الگوی معماری مطرح میشود و با Design Patternهای کلاسیک مانند Factory، Strategy یا Adapter یکسان نیست.
# جمعبندی
MVC یکی از مفاهیم مهم در معماری برنامههای وب است که با تقسیم برنامه به سه بخش اصلی، مسئولیتهای مختلف را از یکدیگر جدا میکند:
Model
↓
دادهها و منطق مرتبط با داده
View
↓
نمایش اطلاعات
Controller
↓
مدیریت درخواست و هماهنگی بخشها
استفاده صحیح از MVC میتواند باعث شود پروژه PHP ساختارمندتر، قابل نگهداریتر و توسعهپذیرتر باشد.
در پروژههای کوچک ممکن است استفاده از MVC ضروری نباشد، اما در پروژههای بزرگتر مانند فروشگاه اینترنتی، CMS، پنل مدیریت، SaaS و نرمافزارهای تحت وب، داشتن یک معماری مشخص اهمیت زیادی پیدا میکند.
اگر مسیر یادگیری PHP را دنبال میکنید، بهتر است MVC را در ادامه مباحثی مانند OOP، Namespace، Composer، Autoload، Dependency Injection و SOLID یاد بگیرید و سپس سراغ معماریهای پیشرفتهتر و فریمورکهایی مانند Laravel بروید.





