PHP: عمليات قاعدة البيانات PDO

آخر تحديث: 2026-08-26

لقد تعلمت أوامر MySQL، لكن الهدف الحقيقي هو إدارة قاعدة البيانات من خلال PHP. PDO (PHP Data Objects) هي طبقة تجريد قواعد البيانات القياسية الموصى بها في PHP — حيث تعمل مجموعة واحدة من الأكواد مع 12 نوعًا من قواعد البيانات. تذكر: تعلم PDO، وتجاهل MySQLi.

1. لماذا PDO؟

PDO MySQLi
قواعد البيانات المدعومة 12 (MySQL/PostgreSQL/SQLite...) MySQL فقط
المعلمات المسماة ✅ :name ❌ ? فقط
استرداد المصفوفات الترابطية ✅ PDO::FETCH_ASSOC ✅
استرداد الكائنات ✅ PDO::FETCH_OBJ ❌ (يتطلب إعدادات إضافية)
وضع الاستثناء ✅ قابل للتكوين ✅ قابل للتكوين
الحداثة 🏆 معيار المجتمع التراث

2. اتصال PDO

PHP
<?php
$host = 'localhost';
$dbname = 'myblog';
$username = 'root';
$password = '';
$charset = 'utf8mb4';

$dsn = "mysql:host={$host};dbname={$dbname};charset={$charset}";

try {
    $pdo = new PDO($dsn, $username, $password, [
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES   => false,
    ]);
    echo "✅ Database connected successfully!<br>";
} catch (PDOException $e) {
    die("❌ Connection failed: " . $e->getMessage());
}
?>
خيار الاتصال المعنى السبب
ERRMODE_EXCEPTION إثارة استثناءات عند حدوث أخطاء لا للفشل الصامت
FETCH_ASSOC التعيين الافتراضي للمصفوفات الترابطية التنسيق الأكثر استخدامًا
EMULATE_PREPARES => false استخدم العبارات المعدة مسبقًا أمان حقيقي
💡 نصيحة: هذه الخيارات الثلاثة الخاصة بـ PDO هي الإعدادات القياسية — احرص دائمًا على تضمينها عند إنشاء اتصال PDO. يضمن EMULATE_PREPARES => false استخدام العبارات المُعدة مسبقًا الأصلية في MySQL بدلاً من تلك التي يحاكيها PDO.


3. query() — تنفيذ استعلامات SELECT

PHP
<?php
// Simple query
$stmt = $pdo->query("SELECT * FROM users");
$users = $stmt->fetchAll();

// Iterate results
foreach ($users as $user) {
    echo "ID: {$user['id']}, Username: {$user['username']}<br>";
}

// Fetch a single row
$stmt = $pdo->query("SELECT * FROM users WHERE id = 1");
$user = $stmt->fetch();

echo $user['username'];  // John
?>

(1) أوضاع الاسترجاع

PHP
<?php
$stmt = $pdo->query("SELECT id, username FROM users");

// Associative array (default)
$row = $stmt->fetch(PDO::FETCH_ASSOC);
echo $row['username'];

// Numeric index
$row = $stmt->fetch(PDO::FETCH_NUM);
echo $row[1];

// Object
$row = $stmt->fetch(PDO::FETCH_OBJ);
echo $row->username;

// Fetch a single column
$usernames = $stmt->fetchAll(PDO::FETCH_COLUMN, 1);
print_r($usernames);  // ['John', 'Jane', ...]
?>

4. العبارات المعدة مسبقًا (أساسي!)

تعد العبارات المُعدة مسبقًا هي المفتاح لمنع هجمات حقن SQL:

▶ مثال: استعلام آمن للمستخدم

PHP
<?php
// ❌ Dangerous: direct SQL concatenation (SQL injection vulnerability)
// $stmt = $pdo->query("SELECT * FROM users WHERE username = '$input'");

// ✅ Safe: prepared statement
$username = $_GET['username'] ?? '';

$sql = "SELECT * FROM users WHERE username = :username";
$stmt = $pdo->prepare($sql);
$stmt->execute(['username' => $username]);
$user = $stmt->fetch();

if ($user) {
    echo "Found user: {$user['username']}";
} else {
    echo "User not found";
}
?>
▶ جرّب الكود

(1) إدراج

PHP
<?php
$sql = "INSERT INTO users (username, email, password, age) 
        VALUES (:username, :email, :password, :age)";

$stmt = $pdo->prepare($sql);
$stmt->execute([
    'username' => 'Alex',
    'email'    => 'alex@example.com',
    'password' => password_hash('123456', PASSWORD_DEFAULT),
    'age'      => 24,
]);

$newId = $pdo->lastInsertId();
echo "New user ID: {$newId}";
?>

(2) تحديث

PHP
<?php
$sql = "UPDATE users SET age = :age WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute(['age' => 27, 'id' => 1]);

echo "Affected {$stmt->rowCount()} row(s)";
?>

(3) حذف

PHP
<?php
$sql = "DELETE FROM users WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute(['id' => 5]);

echo "Deleted {$stmt->rowCount()} row(s)";
?>

5. تطبيق CRUD الكامل عمليًّا

▶ مثال: صفحة إدارة المستخدمين

PHP 📖 للعرض فقط
<?php
// Database connection (same as above, omitted for brevity)
$pdo = new PDO($dsn, $username, $password, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);

// Handle form submissions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $action = $_POST['action'] ?? '';
    
    if ($action === 'add') {
        $stmt = $pdo->prepare(
            "INSERT INTO users (username, email, password, age) 
             VALUES (:username, :email, :password, :age)"
        );
        $stmt->execute([
            'username' => $_POST['username'],
            'email'    => $_POST['email'],
            'password' => password_hash($_POST['password'], PASSWORD_DEFAULT),
            'age'      => (int)$_POST['age'],
        ]);
        echo "<p style='color:green'>User added successfully!</p>";
    } elseif ($action === 'delete') {
        $stmt = $pdo->prepare("DELETE FROM users WHERE id = :id");
        $stmt->execute(['id' => (int)$_POST['id']]);
        echo "<p style='color:green'>User deleted!</p>";
    }
}

// Query all users
$users = $pdo->query("SELECT * FROM users ORDER BY id DESC")->fetchAll();
?>

<h2>User Management</h2>

<table border="1" cellpadding="8">
    <tr><th>ID</th><th>Username</th><th>Email</th><th>Age</th><th>Registered</th><th>Actions</th></tr>
    <?php foreach ($users as $u): ?>
    <tr>
        <td><?= $u['id'] ?></td>
        <td><?= htmlspecialchars($u['username']) ?></td>
        <td><?= htmlspecialchars($u['email']) ?></td>
        <td><?= $u['age'] ?></td>
        <td><?= $u['created_at'] ?></td>
        <td>
            <form method="POST" style="display:inline">
                <input type="hidden" name="action" value="delete">
                <input type="hidden" name="id" value="<?= $u['id'] ?>">
                <button type="submit" onclick="return confirm('Confirm deletion?')">Delete</button>
            </form>
        </td>
    </tr>
    <?php endforeach; ?>
</table>

<h3>Add User</h3>
<form method="POST">
    <input type="hidden" name="action" value="add">
    <input type="text" name="username" placeholder="Username" required>
    <input type="email" name="email" placeholder="Email" required>
    <input type="password" name="password" placeholder="Password" required>
    <input type="number" name="age" placeholder="Age">
    <button type="submit">Add</button>
</form>
56 سطر من الكود المنطقي (تجاوز الحد 40, للعرض فقط)

❓ أسئلة شائعة

س PDO أم MySQLi — أيهما يجب أن أختار؟
ج PDO. فهو يدعم 12 نوعًا من قواعد البيانات (يمكنك التبديل بين قواعد البيانات دون الحاجة إلى إعادة كتابة الكود)، ويتميز ببناء جمل أوامر مُعدة مسبقًا أكثر إيجازًا (:name المعلمات المسماة)، كما أنه المعيار المقبول لدى مجتمع PHP. أما MySQLi فهو مناسب فقط لصيانة المشاريع القديمة.
س ما الفرق بين fetch() وfetchAll()؟
ج تسترد fetch() صفًا واحدًا في كل مرة (كل استدعاء يُرجع صفًا واحدًا) — وهي مناسبة لمجموعات النتائج الكبيرة. أما fetchAll() فتسترد كل البيانات إلى مصفوفة دفعة واحدة — وهي أبسط، لكنها قد تستهلك قدرًا كبيرًا من الذاكرة في حالة مجموعات البيانات الكبيرة.

📖 ملخص

📝 تمارين

  1. استخدم PDO للاتصال بقاعدة بيانات myblog، واسترجع جميع البيانات من جدول users، وعرضها في جدول.
  2. قم بإنشاء صفحة تسجيل تحتوي على نموذج لإدخال اسم المستخدم/البريد الإلكتروني/كلمة المرور. استخدم العبارات المعدة مسبقًا في PDO لإضافة المستخدم الجديد (لا تنسَ password_hash).
  3. أضف زر «حذف» إلى كل صف في الجدول الوارد في التمرين 1. ويجب أن يؤدي النقر عليه إلى حذف سجل المستخدم المقابل.
Web-Tutorial.com

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

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

100%