آموزش ساخت سیستم مدیریت تاریخچه

آموزش ساخت سیستم مدیریت تاریخچه با PHP

آموزش ساخت سیستم مدیریت تاریخچه با PHP

سیستم‌های مدیریت تاریخچه (Version Control Systems) ابزارهای حیاتی در توسعه نرم‌افزار هستند که امکان ردیابی تغییرات در کد، بازگشت به نسخه‌های قبلی و همکاری تیمی را فراهم می‌کنند. در این مقاله، به بررسی نحوه ساخت یک سیستم مدیریت تاریخچه ساده با استفاده از PHP خواهیم پرداخت. این سیستم، اگرچه به پیچیدگی ابزارهایی مانند Git نمی‌رسد، اما می‌تواند درک عمیقی از مفاهیم اساسی کنترل نسخه ارائه دهد و برای پروژه‌های کوچک و متوسط مناسب باشد.

مفاهیم کلیدی

قبل از شروع، لازم است با مفاهیم کلیدی مرتبط با سیستم‌های مدیریت تاریخچه آشنا شویم:

  • Repository (مخزن): مکانی که تمام نسخه‌های فایل‌ها و تاریخچه تغییرات در آن ذخیره می‌شود.
  • Commit (ثبت): یک snapshot از وضعیت فایل‌ها در یک زمان مشخص. هر commit شامل یک پیام (message) است که توضیح می‌دهد چه تغییراتی اعمال شده است.
  • Revision (بازبینی): یک نسخه خاص از فایل‌ها در یک commit خاص.
  • Branch (شاخه): یک خط زمانی جداگانه از توسعه که از یک commit خاص منشعب می‌شود.
  • Merge (ادغام): فرآیند ترکیب تغییرات از یک شاخه به شاخه دیگر.

طراحی سیستم

سیستم مدیریت تاریخچه ما شامل اجزای زیر خواهد بود:

  • پایگاه داده: برای ذخیره اطلاعات مربوط به commitها، revisionها و فایل‌ها.
  • رابط کاربری: برای تعامل با سیستم، شامل ثبت تغییرات، مشاهده تاریخچه و بازگرداندن نسخه‌های قبلی.
  • کلاس‌های PHP: برای مدیریت عملیات مربوط به پایگاه داده و منطق سیستم.

ساختار پایگاه داده

برای ذخیره اطلاعات، از سه جدول استفاده خواهیم کرد:

  • files: شامل اطلاعات مربوط به فایل‌ها (نام فایل، مسیر فایل، محتوای فایل).
  • commits: شامل اطلاعات مربوط به commitها (شناسه commit، تاریخ commit، پیام commit، شناسه فایل).
  • revisions: شامل اطلاعات مربوط به revisionها (شناسه revision، شناسه commit، محتوای revision).

پیاده‌سازی سیستم

در این بخش، به پیاده‌سازی سیستم با استفاده از PHP خواهیم پرداخت. برای سادگی، از یک پایگاه داده SQLite استفاده می‌کنیم.

اتصال به پایگاه داده

ابتدا، یک تابع برای اتصال به پایگاه داده SQLite ایجاد می‌کنیم:


ایجاد جداول

سپس، جداول پایگاه داده را ایجاد می‌کنیم:

exec("
        CREATE TABLE IF NOT EXISTS files (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            filename TEXT NOT NULL,
            filepath TEXT NOT NULL,
            content TEXT NOT NULL
        )
    ");

    $db->exec("
        CREATE TABLE IF NOT EXISTS commits (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            commit_date DATETIME DEFAULT CURRENT_TIMESTAMP,
            message TEXT NOT NULL,
            file_id INTEGER NOT NULL,
            FOREIGN KEY (file_id) REFERENCES files(id)
        )
    ");

    $db->exec("
        CREATE TABLE IF NOT EXISTS revisions (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            commit_id INTEGER NOT NULL,
            content TEXT NOT NULL,
            FOREIGN KEY (commit_id) REFERENCES commits(id)
        )
    ");
}
?>

ثبت تغییرات (Commit)

تابع زیر، تغییرات را در فایل ثبت می‌کند:

prepare("INSERT INTO files (filename, filepath, content) VALUES (:filename, :filepath, :content)");
    $stmt->bindValue(':filename', $filename, SQLITE3_TEXT);
    $stmt->bindValue(':filepath', $filepath, SQLITE3_TEXT);
    $stmt->bindValue(':content', $content, SQLITE3_TEXT);
    $stmt->execute();

    $file_id = $db->lastInsertRowid();

    $stmt = $db->prepare("INSERT INTO commits (message, file_id) VALUES (:message, :file_id)");
    $stmt->bindValue(':message', $message, SQLITE3_TEXT);
    $stmt->bindValue(':file_id', $file_id, SQLITE3_INTEGER);
    $stmt->execute();

    $commit_id = $db->lastInsertRowid();

    $stmt = $db->prepare("INSERT INTO revisions (commit_id, content) VALUES (:commit_id, :content)");
    $stmt->bindValue(':commit_id', $commit_id, SQLITE3_INTEGER);
    $stmt->bindValue(':content', $content, SQLITE3_TEXT);
    $stmt->execute();
}
?>

مشاهده تاریخچه

تابع زیر، تاریخچه تغییرات یک فایل را برمی‌گرداند:

prepare("
        SELECT commits.commit_date, commits.message, revisions.content
        FROM commits
        INNER JOIN revisions ON commits.id = revisions.commit_id
        INNER JOIN files ON commits.file_id = files.id
        WHERE files.filename = :filename
        ORDER BY commits.commit_date DESC
    ");
    $stmt->bindValue(':filename', $filename, SQLITE3_TEXT);
    $result = $stmt->execute();

    $history = [];
    while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
        $history[] = $row;
    }

    return $history;
}
?>

بازگرداندن به نسخه قبلی (Revert)

تابع زیر، فایل را به یک نسخه قبلی بازمی‌گرداند:

prepare("
        SELECT content
        FROM revisions
        WHERE id = :revision_id
    ");
    $stmt->bindValue(':revision_id', $revision_id, SQLITE3_INTEGER);
    $result = $stmt->execute();

    $row = $result->fetchArray(SQLITE3_ASSOC);
    $content = $row['content'];

    $stmt = $db->prepare("UPDATE files SET content = :content WHERE filename = :filename");
    $stmt->bindValue(':content', $content, SQLITE3_TEXT);
    $stmt->bindValue(':filename', $filename, SQLITE3_TEXT);
    $stmt->execute();
}
?>

رابط کاربری (نمونه)

یک رابط کاربری ساده با استفاده از HTML و PHP می‌تواند به شکل زیر باشد:

<form method="post" action="commit.php">
    <textarea name="content" rows="10" cols="50"></textarea>
    <input type="text" name="filename" placeholder="نام فایل">
    <input type="text" name="message" placeholder="پیام commit">
    <button type="submit">ثبت تغییرات</button>
</form>

<form method="post" action="history.php">
    <input type="text" name="filename" placeholder="نام فایل">
    <button type="submit">مشاهده تاریخچه</button>
</form>

نکات تکمیلی

  • امنیت: در یک سیستم واقعی، باید اقدامات امنیتی مناسبی را برای جلوگیری از دسترسی غیرمجاز و حملات تزریق SQL انجام دهید.
  • مقیاس‌پذیری: برای پروژه‌های بزرگ، استفاده از یک پایگاه داده قوی‌تر مانند MySQL یا PostgreSQL و بهینه‌سازی کوئری‌ها ضروری است.
  • رابط کاربری: یک رابط کاربری گرافیکی (GUI) می‌تواند تجربه کاربری را بهبود بخشد.
  • Branching و Merging: پیاده‌سازی قابلیت‌های branching و merging می‌تواند سیستم را قدرتمندتر کند.

این مقاله، یک معرفی اولیه به ساخت سیستم مدیریت تاریخچه با PHP بود. با استفاده از این مبانی، می‌توانید سیستم خود را گسترش دهید و قابلیت‌های بیشتری به آن اضافه کنید.