مشروع تدريبي في البرمجة الكائنية

لقد درست 5 دروس في البرمجة الموجهة للكائنات. والآن دعنا ندمج كل هذه المعرفة معًا من خلال مشروعين: نظام مستخدم متكامل يغطي مفاهيم الوراثة/القوائم/السمات/الواجهات، وإطار عمل بسيط يمنحك لمحة أولية عن بنية MVC.

1. المشروع الأول: نظام إدارة أدوار المستخدمين

اجمع بين الفئات، والوراثة، والقوائم التعدادية، والسمات، والواجهات لإنشاء إطار عمل متكامل لإدارة أدوار المستخدمين.

▶ مثال: نظام مستخدم كامل قائم على البرمجة الكائنية

PHP
<?php
// === Enums ===
enum UserRole: string {
    case ADMIN  = 'admin';
    case EDITOR = 'editor';
    case MEMBER = 'member';
    case GUEST  = 'guest';
}

enum UserStatus: string {
    case ACTIVE   = 'active';
    case INACTIVE = 'inactive';
    case BANNED   = 'banned';
}

// === Interfaces ===
interface Loggable {
    public function getLogIdentifier(): string;
}

interface Manageable {
    public function canAccess(string $resource): bool;
    public function getPermissions(): array;
}

// === Traits ===
trait HasTimestamps {
    public readonly string $createdAt;
    public readonly string $updatedAt;

    public function touch(): void {
        $now = date("Y-m-d H:i:s");
        if (!isset($this->createdAt)) {
            $this->createdAt = $now;
        }
        $this->updatedAt = $now;
    }
}

trait ArraySerializable {
    public function toArray(): array {
        return get_object_vars($this);
    }
}

// === Base Class ===
abstract class User implements Loggable, Manageable {
    use HasTimestamps, ArraySerializable;

    public function __construct(
        public readonly string $id,
        public string $name,
        public string $email,
        public UserRole $role = UserRole::MEMBER,
        public UserStatus $status = UserStatus::ACTIVE,
    ) {
        $this->touch();
    }

    public function getLogIdentifier(): string {
        return "User#{$this->id} ({$this->name})";
    }

    abstract public function canAccess(string $resource): bool;
    abstract public function getPermissions(): array;
    abstract public function getRoleLabel(): string;
}

// === Concrete Role Classes ===
class Admin extends User {
    public function __construct(
        string $id, string $name, string $email
    ) {
        parent::__construct($id, $name, $email, UserRole::ADMIN);
    }

    public function canAccess(string $resource): bool {
        return true;  // Admin can access everything
    }

    public function getPermissions(): array {
        return ['create', 'read', 'update', 'delete', 'manage_users', 'system_config'];
    }

    public function getRoleLabel(): string {
        return '🔧 Admin';
    }
}

class Editor extends User {
    public function __construct(
        string $id, string $name, string $email
    ) {
        parent::__construct($id, $name, $email, UserRole::EDITOR);
    }

    public function canAccess(string $resource): bool {
        return in_array($resource, ['articles', 'media', 'comments']);
    }

    public function getPermissions(): array {
        return ['create', 'read', 'update', 'manage_comments'];
    }

    public function getRoleLabel(): string {
        return '✏️ Editor';
    }
}

class Member extends User {
    public function __construct(
        string $id, string $name, string $email
    ) {
        parent::__construct($id, $name, $email, UserRole::MEMBER);
    }

    public function canAccess(string $resource): bool {
        return in_array($resource, ['articles', 'comments', 'profile']);
    }

    public function getPermissions(): array {
        return ['read', 'comment'];
    }

    public function getRoleLabel(): string {
        return '👤 Member';
    }
}

// === Access Manager ===
class AccessManager {
    public function checkAccess(User $user, string $resource): string {
        if ($user->status === UserStatus::BANNED) {
            return "{$user->getRoleLabel()} {$user->name}: Banned, access denied for {$resource}";
        }
        
        $allowed = $user->canAccess($resource)
            ? "✅ Access Granted" : "❌ Access Denied";
        
        return "{$user->getRoleLabel()} {$user->name}: {$allowed} {$resource}";
    }
    
    public function listAllAccess(array $users, array $resources): void {
        foreach ($users as $user) {
            echo "<h4>{$user->getLogIdentifier()}</h4>";
            echo "Permissions: " . implode(', ', $user->getPermissions()) . "<br>";
            foreach ($resources as $res) {
                echo $this->checkAccess($user, $res) . "<br>";
            }
        }
    }
}

// === Test the System ===
$users = [
    new Admin("u1", "John", "admin@example.com"),
    new Editor("u2", "Jane", "editor@example.com"),
    new Member("u3", "Bob", "member@example.com"),
];

$resources = ['articles', 'media', 'comments', 'system_config', 'manage_users'];

$manager = new AccessManager();
$manager->listAllAccess($users, $resources);

// Test enum + serialization
echo "<br>Admin data: " . json_encode($users[0]->toArray(), JSON_UNESCAPED_UNICODE);
?>
▶ جرّب الكود

2. المشروع الثاني: إطار عمل MVC بسيط

افهم مفهوم MVC المتمثل في «الموجه» (Router) و«وحدة التحكم» (Controller) و«العرض» (View) — فهذه هي الفكرة الأساسية الكامنة وراء أطر العمل مثل Laravel.

▶ مثال: نموذج MVC المصغر

PHP
<?php
// === Router ===
class Router {
    private array $routes = [];

    public function get(string $path, callable $handler): void {
        $this->routes['GET'][$path] = $handler;
    }

    public function post(string $path, callable $handler): void {
        $this->routes['POST'][$path] = $handler;
    }

    public function dispatch(string $method, string $uri): void {
        $path = parse_url($uri, PHP_URL_PATH);
        $handler = $this->routes[$method][$path] ?? null;

        if ($handler) {
            echo $handler($_GET);
        } else {
            http_response_code(404);
            echo "<h2>404 — Page Not Found</h2>";
        }
    }
}

// === View Base ===
class View {
    public static function render(string $template, array $data = []): string {
        extract($data);
        ob_start();
        include __DIR__ . "/{$template}.php";
        return ob_get_clean();
    }
}

// === Controller Base ===
abstract class Controller {
    protected function json(array $data, int $code = 200): void {
        http_response_code($code);
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode($data, JSON_UNESCAPED_UNICODE);
    }
}

// === Concrete Controller ===
class HomeController extends Controller {
    public function index(): void {
        echo View::render('home', [
            'title'   => 'Home',
            'message' => 'Welcome to my blog!',
        ]);
    }

    public function about(): void {
        echo View::render('about', [
            'title'   => 'About Us',
            'team'    => ['John', 'Jane', 'Bob'],
            'version' => '1.0.0',
        ]);
    }

    public function api(): void {
        $this->json([
            'status' => 'ok',
            'data'   => ['version' => '1.0.0', 'uptime' => time()],
        ]);
    }
}

// === Set Up Routes ===
$router = new Router();
$home = new HomeController();

$router->get('/', fn() => $home->index());
$router->get('/about', fn() => $home->about());
$router->get('/api/status', fn() => $home->api());

// === Launch the App ===
$router->dispatch($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);
?>
▶ جرّب الكود

ملف العرض المرفق home.php:

PHP
<!DOCTYPE html>
<html lang="en">
<head><title><?= $title ?></title></head>
<body>
    <h1><?= $message ?></h1>
    <p>This page is built using MVC principles.</p>
</body>
</html>

3. التحول الفكري: من البرمجة الإجرائية إلى البرمجة الموجهة للكائنات

التفكير الإجرائي التفكير في البرمجة الكائنية
"أحتاج إلى قراءة بيانات المستخدم" → كتابة دالة getUser() "ما هو المستخدم؟ ما هي خصائصه وسلوكياته؟" → تصميم فئة User
البيانات والوظائف موزعة على ملفات مختلفة البيانات + السلوك مغلفة في فئة
تكرار في الكود → انسخ والصق أو استخرج دالة تكرار في الكود → استخدم الوراثة أو السمات
تمرير سلاسل 'admin' للأذونات تمرير UserRole::ADMIN كقائمة، مع ضمان سلامة الأنواع
💡 نصيحة: البرمجة الموجهة للكائنات (OOP) هي وسيلة وليست غاية. ولا بأس بالبرمجة الإجرائية في البرامج النصية الصغيرة. انتقل إلى البرمجة الموجهة للكائنات عندما تلاحظ العلامات التالية: (1) استمرار تمرير نفس المعلمات بين الدوال؛ (2) تراكم المتغيرات العالمية؛ (3) استناد الشروط إلى «سلاسل النصوص» (if ($role === 'admin')).

❓ أسئلة شائعة

س ما هي المهمة الفعلية لوحدة التحكم (Controller) في نموذج MVC؟
ج وحدة التحكم هي «مدير حركة المرور» — فهي تستقبل الطلب، وتستدعي النموذج (Model) للحصول على البيانات، وتختار العرض (View) لعرضه. وهي لا تتولى معالجة منطق الأعمال بنفسها (فهذه مهمة النموذج) ولا تكتب كود HTML (فهذه مهمة العرض).
س هل يجب أن أقوم بإنشاء إطار عمل خاص بي أم أستخدم إطار عمل موجود بالفعل؟
ج قم بإنشاء إطار عمل مصغر خلال مرحلة التعلم لفهم المبادئ (تمامًا مثل هذا الدرس). استخدم Laravel/Symfony في بيئة الإنتاج. بعد أن تقوم بإنشاء Router/Controller/View الخاص بك مرة واحدة، سيجعلك استخدام Laravel تقول: «آه، إذن هذا ما يحدث وراء الكواليس».

❓ أسئلة شائعة

س كيف يمكنني اختبار إطار العمل المصغر MVC الذي قمت بإنشائه؟
ج قم بتشغيل Apache أو خادم PHP المدمج (php -S localhost:8000)، ثم انتقل إلى http://localhost:8000 في متصفحك. يقوم الموزع (dispatcher) بتوجيه الطلب إلى وحدة التحكم المناسبة بناءً على عنوان URL. استخدم var_dump() أو error_log() لتصحيح الأخطاء خطوة بخطوة.

📖 ملخص

📝 تمارين

  1. استنادًا إلى نظام المستخدم، أضف دورًا باسم Guest (يمكنه الوصول إلى المقالات فقط، ولا يمتلك أي أذونات تحرير على الإطلاق) وأضفه إلى مجموعة الاختبارات.
  2. أضف طريقة addRoute('GET/POST', $path, $handler) إلى جهاز التوجيه بحيث يمكن لمكالمة واحدة تسجيل كلتا الطريقتين.
  3. أضف مكونًا UserController إلى إطار عمل MVC يقوم بتنفيذ قائمة بالمستخدمين (يتم قراءتها من مصفوفة) وصفحة تفاصيل المستخدم (الاستعلام حسب المعرّف).
Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%