دروس8 دقايق ديال القراية

شنو هو MVC فالبرمجة؟ مثال PHP و MySQL بالدارجة

شنو هو MVC فالبرمجة؟ كنرتبو CRUD ديال PHP و MySQL بلا framework: Model وView وController وRouter، مع مثال PHP كامل بالدارجة.

كاين حتى ب : Français

Mehdi بلباس الأستاذ، غلاف المقال: MVC فـ PHP

MVC (Model, View, Controller) هو طريقة باش نقسمو الكود ديال التطبيق على 3 أدوار: Model كيتكلم مع la base، View كتعرض HTML، وController كيستقبل الطلب وكينسق بيناتهم. فدرس E10، طبقنا هاد الفكرة على CRUD حقيقي بـ PHP و MySQL، بلا framework، وزدنا Router كيدخل منو كل طلب من باب واحد. وهادي هي نفس التنظيم اللي غادي تلقى فـ Laravel.

علاش الفيشي الواحد كيولي كيكسر كلشي؟

فالبداية، كلشي كيكون فـ index.php: الكونيكسيون، la requête SQL، الخدمة ديال الفورم، والطابلو ديال HTML. هادا هو الفيشي اللي بان فالبداية ديال الدرس، مختصر:

php
<?php require "db.php";
$users = $pdo->query("SELECT * FROM users")->fetchAll();
if ($_SERVER["REQUEST_METHOD"] === "POST") {
  $pdo->prepare("INSERT INTO users ...")->execute([...]);
}
?>
<h1>Les utilisateurs</h1>
<table>
<?php foreach ($users as $u): ?>
  <tr><td><?= $u["nom"] ?></td></tr>
<?php endforeach; ?>
</table>

SQL والمنطق و HTML مخلطين. ملي كيكون المشروع صغير، كيدوز. ولكن ملي كيكبر، ما كتبقاش عارف فين تبدل، وأي تعديل صغير يقدر يكسر ليك شي حاجة أخرى.

شنو هو MVC، بمثال ساهل؟

فالدرس خدمنا بمثال الريسطو:

  • Controller هو السرباي: كياخد la commande وكيعرف شكون خاصو يخدم؛
  • Model هو الكوزينة: كيتكلم مع MySQL وكيوجد المعلومات؛
  • View هي الطبسيل: كتعرض المعلومات فـ HTML، وصافي.

فالدوسيات، كتولي عندنا هاد البنية:

text
app/
  Models/User.php
  Views/users/index.php
  Controllers/UserController.php
config/db.php
public/index.php      ← الباب الوحيد ديال السيت

Model: هو الوحيد اللي كيتكلم مع la base

فـ app/Models/User.php، كل requête SQL ديال CRUD كتولي méthode. والكلاس كتاخد $pdo من db.php:

php
<?php
class User {
  public function __construct(private PDO $pdo) {}

  public function all(): array {
    return $this->pdo->query("SELECT * FROM users")->fetchAll();
  }

  public function find(int $id): array|false {
    $stmt = $this->pdo->prepare("SELECT * FROM users WHERE id = ?");
    $stmt->execute([$id]);
    return $stmt->fetch();
  }

  public function create(string $nom, string $email): void {
    $stmt = $this->pdo->prepare("INSERT INTO users (nom, email) VALUES (?, ?)");
    $stmt->execute([$nom, $email]);
  }
  // update() et delete() : même principe
}

القاعدة: Model ما كيعرف والو على HTML، وما كيشوفش $_POST. غير المعلومات. وفالدرس شفنا جوج فوائد: إلا احتاجيتي نفس la requête فبلاصة أخرى، كتعيط للـ méthode وما كتعاودش تكتب SQL؛ وإلا شي نهار بدلتي la base، كتبدل غير Model، والباقي ما كيتقاس.

View: HTML نقي، بلا SQL

app/Views/users/index.php ما بقا فيها غير الطابلو. كتوصلها $users واجدة:

php
<h1>Les utilisateurs</h1>
<a href="/users/create">Ajouter</a>
<table>
<?php foreach ($users as $u): ?>
  <tr>
    <td><?= htmlspecialchars($u["nom"]) ?></td>
    <td><?= htmlspecialchars($u["email"]) ?></td>
    <td><a href="/users/edit?id=<?= $u["id"] ?>">Modifier</a></td>
  </tr>
<?php endforeach; ?>
</table>

ما كاين حتى SELECT، وما كاين حتى $pdo: View ما كتسولش la base. ولكن htmlspecialchars ديما فـ View، حيت هي اللي كتعرض، إذن هي اللي خاصها تحمي من XSS. والكتابة بـ <?= و endforeach كتخلي HTML نقي، حتى designer ما كيعرفش PHP يقدر يفهمو. وبغيتي تبدل le design؟ كتبدل غير View.

Controller: كينسق، بلا SQL وبلا HTML

app/Controllers/UserController.php فيه méthode لكل صفحة. la méthode index فيها سطر واحد مهم، ومن بعد render:

php
<?php
class UserController {
  public function __construct(private User $user) {}

  public function index(): void {
    $users = $this->user->all();
    $this->render("users/index", ["users" => $users]);
  }

  private function render(string $view, array $data): void {
    extract($data);    // ["users" => …] devient $users
    require __DIR__ . "/../Views/$view.php";
  }
}

render فونكسيون صغيرة: extract كترد الطابلو variables، و require كيجيب View.

فين نديرو la validation ديال الفورم؟

فـ Controller، ماشي فـ View. la méthode store كتقرا $_POST، كتتأكد من l'email، ومن بعد كتعيط لـ Model:

php
public function store(): void {
  $email = trim($_POST["email"] ?? "");
  if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    $this->render("users/create", ["erreur" => "Email invalide"]);
    return;
  }
  $this->user->create($_POST["nom"], $email);
  header("Location: /users");
  exit;
}

إلا كان l'email غالط، كنرجعو للفورم مع رسالة. وإلا كان مزيان، header("Location: …") و exit، بحال فـ CRUD. Controller ما كيكتب لا SQL لا HTML.

Router: شكون كيعرف أنهي Controller نعيطو ليه؟

كل الطلبات كتدخل من public/index.php، وهادا كنسميوه front controller. وفـ .htaccess، كاين قاعدة كتصيفط أي URL لـ index.php بلا ما يبانو الفيشيات ديال PHP:

apache
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]

وفـ index.php، طابلو ديال les routes كيربط كل « méthode + chemin » بـ Controller و méthode:

php
<?php
require __DIR__ . "/../config/db.php";
require __DIR__ . "/../app/Models/User.php";
require __DIR__ . "/../app/Controllers/UserController.php";

$routes = [
  "GET /users"        => [UserController::class, "index"],
  "GET /users/create" => [UserController::class, "create"],
  "POST /users"       => [UserController::class, "store"],
  "GET /users/edit"   => [UserController::class, "edit"],
];
$method = $_SERVER["REQUEST_METHOD"];
$path = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
$route = $routes["$method $path"] ?? null;
if (!$route) { http_response_code(404); exit("Page introuvable"); }

[$class, $action] = $route;
(new $class(new User($pdo)))->$action();

إلا la route ما كايناش، الزائر كيشوف 404 نقية، ماشي صفحة بيضة عامرة بالأخطاء.

الطريق كامل ديال GET /users

  1. le navigateur كيطلب /users.
  2. public/index.php كيستقبلها، و Router كيصيفطها لـ UserController::index().
  3. index() كتسول Model User على المستخدمين.
  4. Model كيدير SELECT فـ MySQL وكيرجع النتيجة.
  5. Controller كيعطي $users لـ View.
  6. View كتبني HTML، وهو اللي كيرجع للـ navigateur.

كل واحد دار الخدمة ديالو، وما دخلش فخدمة الآخر.

والـ login ديال الدرس اللي فات؟

كيولي méthode خاصة فـ Controller، كنعيطو ليها فالبداية ديال كل صفحة محمية:

php
private function requireLogin(): void {
  if (!isset($_SESSION["user_id"])) {    // cours E09
    header("Location: /login");
    exit;
  }
}

public function index(): void {
  $this->requireLogin();
  $users = $this->user->all();
  $this->render("users/index", ["users" => $users]);
}

شنو العلاقة مع Laravel؟

فالـ récap ديال الدرس، حطينا جوج التنظيمات حدا بعضياتهم:

الدورفهاد الدرسفـ Laravel
Modelapp/Models/User.phpapp/Models/User.php
Viewapp/Views/users/resources/views/users/
Controllerapp/Controllers/app/Http/Controllers/
Routerpublic/index.phproutes/web.php

إلا فهمتي هاد النسخة اللي درناها بيدينا، Laravel غادي يبان ليك ساهل بزاف: غادي تعرف شنو كيدير الـ framework فبلاصتك.

أسئلة كيتعاودو

فين نحطو SQL فمشروع MVC؟

فـ Model، وغير تما. فالدرس، كل requête ديال CRUD ولات méthode فـ User (all، find، create، update، delete). Controller كيعيط ليهم، و View عمرها ما كتشوف $pdo.

واش خاص framework باش ندير MVC فـ PHP؟

لا. الدرس كيبني MVC كامل بـ PHP بوحدو: 3 دوسيات، فونكسيون render، و Router فشي سطور فـ public/index.php. و framework بحال Laravel كيدير نفس الأدوار أوتوماتيكيا.

شنو الفرق بين MVC و Laravel؟

MVC طريقة باش ترتب الكود؛ و Laravel framework كيطبقها وكيزيد بزاف ديال الأدوات. الفيشيات تقريبا كيتقابلو واحد بواحد: routes/web.php هو Router، app/Http/Controllers/ هما Controllers، و resources/views/ هما Views.

فين نتأكدو من الفورم: فـ Controller ولا فـ View؟

فـ Controller. la méthode store كتتأكد من l'email بـ filter_var، وإلا كان غالط كترجع الفورم مع رسالة. View غير كتعرض هاد الرسالة.

شنو خاصك تحفظ

  • Model كيتكلم مع MySQL، وما كيعرفش HTML ولا $_POST.
  • View كتعرض، ما فيها حتى SQL، وكتحمي المعلومات بـ htmlspecialchars.
  • Controller كيستقبل الطلب، كيتأكد من المعلومات، كيعيط لـ Model، وكيختار View.
  • Router كيدخل كل الطلبات من public/index.php، وكيرد 404 نقية إلا la route ما كايناش.
  • هاد التنظيم هو اللي فـ Laravel و Symfony.

شوف الدرس

الدرس كامل (5 دقايق و14 ثانية، بالدارجة) فالصفحة ديالو: نظّم الكود ديالك بـ MVC (E10).

  • 0:00 المقدمة: الكود spaghetti
  • 0:29 الفكرة: 3 أدوار، الريسطو، والدوسيات
  • 1:06 Model
  • 1:51 View
  • 2:30 Controller
  • 3:15 Router (front controller)
  • 3:59 الطريق ديال requête و requireLogin
  • 4:38 Récap، Laravel والتحدي

زيد قدام

المصادر

Quiz: 3 أسئلة باش تتأكد

حتى حاجة ما كتصيفط: الأجوبة ديالك كيبقاو ف المتصفح ديالك.

  1. فمشروع MVC، فين خاصها تكون la requête SELECT * FROM users؟
  2. شنو الدور ديال public/index.php فهاد الدرس؟
  3. علاش htmlspecialchars كتكون فـ View؟

بارطاجي

تكتب من الدرس والنص ديالو بمساعدة أدوات الذكاء الاصطناعي، وراجعو وتأكد منو Mehdi Laraibi نهار 4 نونبر 2026.