في هذا الدرس 6تصفّح المواضيع
أوامر تعريف وهيكلة البيانات (DDL) مثل CREATE DATABASE وCREATE TABLE وALTER TABLE لا تُرجع صفوف نتائج، ولذلك تُنفذ مباشرة عبر الدالة $pdo->exec($sql).
- تنفذ
$pdo->exec($sql)أمر SQL واحداً لا يُرجع صفوفاً، وتُرجع الرقم0لأوامر الهيكلة (أوfalseعند الفشل). - لا تدمج مدخلات المستخدم أبداً داخل
$pdo->exec()؛ فأسماء الجداول والأعمدة في ملفات التهجير يجب أن تكون ثابتة في الكود المصدري. - أضف العبارة
IF NOT EXISTSفيCREATE TABLE IF NOT EXISTSلتتمكن من تشغيل سكريبت التهجير بأمان دون خطأ وجود الجدول مسبقاً.
تنفذ $pdo->exec($sql) أمر إنشاء جدول settings في الذاكرة وتُرجع 0 دلالةً على نجاح أمر الهيكلة.
<?php
$pdo = new PDO('sqlite::memory:');
$sql = 'CREATE TABLE IF NOT EXISTS settings (
key_name VARCHAR(64) PRIMARY KEY,
key_value TEXT NOT NULL
)';
$res = $pdo->exec($sql);
echo "DDL executed, return: $res\n";
عند إنشاء قاعدة بيانات MySQL أو MariaDB جديدة عبر PDO، اتصل بالخادم أولاً بدون تحديد dbname في نص DSN، ثم حدد الترميز CHARACTER SET utf8mb4.
- ترميز MySQL القديم
utf8(أوutf8mb3) يدعم حتى 3 بايتات فقط للحرف ويفشل عند تخزين الرموز ذات الـ 4 بايتات. - استخدم دائماً
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ciلضمان تخزين النصوص العربية والرموز التعبيرية بدقة كاملة. - بعد إنشاء قاعدة البيانات، انتقل إليها بالأمر
$pdo->exec("USE app_db")أو أعد الاتصال مع تضمينdbname=app_db;charset=utf8mb4.
تحديد CHARACTER SET utf8mb4 مع المقارنة utf8mb4_unicode_ci يضمن دعم الترميز الرباعي والترتيب الأبجدي الصحيح.
<?php
$dbName = 'closetag_store';
$ddl = "CREATE DATABASE IF NOT EXISTS $dbName
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci";
echo str_contains($ddl, 'utf8mb4_unicode_ci') ? "UTF8MB4 DDL Ready\n" : "Missing\n";
يجب أن يحتوي كل جدول علائقي على عمود مفتاح أساسي (PRIMARY KEY) يميز كل سجل بشكل فريد ويسرّع عمليات البحث والربط.
- في MySQL، استخدم
BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEYلتوليد أرقام تعريف موجبة تتزايد تلقائياً مع كل سجل جديد. - حدد الأعمدة الإلزامية بالقيد
NOT NULLوأضف قيماً افتراضية مثلDEFAULT CURRENT_TIMESTAMPلتاريخ الإنشاء. - استخدم النوع
DECIMAL(10, 2)بدلاً منFLOATللمبالغ المالية لتفادي أخطاء التقريب الثنائي في الكسور العشرية.
يعرّف جدول products مفتاحاً أساسياً متزايداً تلقائياً، وعنواناً إلزامياً VARCHAR(150)، وسعراً مالياً دقيقاً DECIMAL(10,2).
<?php
$pdo = new PDO('sqlite::memory:');
$pdo->exec('CREATE TABLE products (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title VARCHAR(150) NOT NULL,
price DECIMAL(10,2) NOT NULL DEFAULT 0.00
)');
$pdo->exec("INSERT INTO products (title, price) VALUES ('Keyboard', 249.50)");
echo "Created ID: " . $pdo->lastInsertId() . "\n";
تمنع قيود عدم التكرار UNIQUE على مستوى قاعدة البيانات تسجيل بريد إلكتروني أو رمز منتج مكرر حتى مع الطلبات المتزامنة، بينما تسرّع الفهارس INDEX استعلامات البحث.
- الاكتفاء بفحص عدم التكرار في كود PHP فقط عرضة لتعارض الطلبات المتزامنة؛ لذا يجب فرض قيد
UNIQUEداخل تصميم الجدول نفسه. - أضف فهارس (Indexes) على الأعمدة التي تُستخدم بكثرة في شروط
WHEREأوJOINأوORDER BY. - اختر أطوالاً مناسبة لأعمدة النصوص المفهرسة (مثل
VARCHAR(190)للبريد الإلكتروني) للحفاظ على خفة الفهرس في الذاكرة.
يفرض عمود email عدم التكرار مباشرة عبر محرك قاعدة البيانات، ويفهرس idx_users_role عمود الصلاحية لتسريع التصفية.
<?php
$pdo = new PDO('sqlite::memory:');
$pdo->exec('CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email VARCHAR(190) NOT NULL UNIQUE,
role VARCHAR(30) NOT NULL DEFAULT "member"
)');
$pdo->exec('CREATE INDEX idx_users_role ON users (role)');
echo "Users table + UNIQUE email + role INDEX ready\n";
تربط المفاتيح الأجنبية (FOREIGN KEY) السجلات الفرعية مثل الطلبات بسجل الأب في جدول المستخدمين، وتتطلب محرك التخزين InnoDB في MySQL.
- يجب أن يطابق عمود المفتاح الأجنبي (
user_id) نوع وإشارة المفتاح الأساسي الأب تماماً (مثلBIGINT UNSIGNEDفي كليهما). - استخدم
ON DELETE CASCADEلحذف السجلات الفرعية تلقائياً مع الأب، أوON DELETE RESTRICTلمنع حذف أب يمتلك سجلات مرتبطة. - ألحق دائماً
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ciبنهاية جملCREATE TABLEفي MySQL.
تعريف المفتاح الأجنبي FOREIGN KEY (dept_id) REFERENCES depts(id) يمنع وجود موظفين مرتبطين بقسم غير موجود ويحفظ التكامل المرجعي.
<?php
$pdo = new PDO('sqlite::memory:');
$pdo->exec('PRAGMA foreign_keys = ON');
$pdo->exec('CREATE TABLE depts (id INTEGER PRIMARY KEY, name TEXT)');
$pdo->exec('CREATE TABLE staff (
id INTEGER PRIMARY KEY,
dept_id INTEGER NOT NULL,
FOREIGN KEY (dept_id) REFERENCES depts(id) ON DELETE CASCADE
)');
echo "Foreign key constraint active\n";
اختيار نوع عمود SQL المناسب يضمن كفاءة التخزين على القرص ومطابقة الأنواع بدقة عند جلب الصفوف إلى PHP 8.4.
- عطّل المحاكاة (
PDO::ATTR_EMULATE_PREPARES => false) لكي تُرجع قاعدة البيانات أعمدة الأعداد الصحيحة كنوعintحقيقي في PHP. - انتبه إلى أن أعمدة
DECIMAL(10, 2)تُرجع عمداً كنصstring(مثل"249.50") للحفاظ على الدقة العشرية المالية دون فقدان. - لا تنفذ أوامر الهيكلة بمدخلات الزوار أبداً؛ بل شغّل ملفات التهجير عبر سطر الأوامر (CLI).
مع تفعيل الأنواع الأصلية، يعود عمود INTEGER مباشرة كعدد صحيح integer داخل PHP.
| نوع عمود SQL | أفضل استخدام | نوع القيمة في PHP | نصيحة التصميم |
|---|---|---|---|
BIGINT UNSIGNED | Primary & Foreign Key IDs | int (on 64-bit PHP) | Match signedness on FKs |
VARCHAR(190) / TEXT | Emails, slugs / Article body | string | Add UNIQUE on emails/slugs |
DECIMAL(10, 2) | Money, prices, tax rates | string (exact precision) | Never use FLOAT for money |
TINYINT(1) / TIMESTAMP | Boolean flags / Audit times | int (0/1) / string | Use DEFAULT CURRENT_TIMESTAMP |
<?php
$pdo = new PDO('sqlite::memory:');
$pdo->exec('CREATE TABLE metrics (id INTEGER PRIMARY KEY, hits INTEGER NOT NULL)');
$pdo->exec('INSERT INTO metrics (hits) VALUES (42)');
$row = $pdo->query('SELECT id, hits FROM metrics')->fetch(PDO::FETCH_ASSOC);
echo gettype($row['hits']) . ":" . $row['hits'] . "\n";
ملخص الدرس
حصاد الدرسمراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي
ماذا تعلّمت في هذا الدرس؟
اختيار نوع عمود SQL المناسب يضمن كفاءة التخزين على القرص ومطابقة الأنواع بدقة عند جلب الصفوف إلى PHP 8.4. عطّل المحاكاة (PDO::ATTR_EMULATE_PREPARES => false) لكي تُرجع قاعدة البيانات أعمدة الأعداد الصحيحة كنوع int حقيقي في PHP. انتبه إلى أن أعمدة DECIMAL(10, 2) تُرجع عمداً كنص string (مثل "249.50") للحفاظ على الدقة العشرية المالية دون فقدان. لا تنفذ أوامر الهيكلة بمدخلات الزوار أبداً؛ بل شغّل ملفات التهجير عبر سطر الأوامر (CLI).
سجّل الدخول لحفظ تقدمك
تابع إنجاز المواضيع والمصطلحات والمهام، وكمّل من آخر خطوة على أي جهاز.
المصطلحات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 PDO Create Tables إنشاء الجداول بـ PDO
- نفّذ أوامر بناء الهيكلة DDL بأمان في PHP 8 عبر PDO::exec لإنشاء قواعد البيانات وجداول UTF8MB4 والمفاتيح الأساسية والفهارس.
- للمراجعة
- 02 Running DDL Statements with PDO exec تنفيذ أوامر الهيكلة عبر PDO::exec
- المفهوم الأساسي لقسم تنفيذ أوامر الهيكلة عبر PDO::exec في لغة PHP الحديثة.
- للمراجعة
- 03 Creating a UTF8MB4 Database in PDO إنشاء قاعدة بيانات بترميز UTF8MB4
- الصياغة البرمجية والتطبيق العملي المباشر لقسم إنشاء قاعدة بيانات بترميز UTF8MB4.
- للمراجعة
- 04 Creating Tables with Primary Keys إنشاء الجداول والمفاتيح الأساسية التلقائية
- قواعد التحقق وأفضل الممارسات القياسية الخاصة بقسم إنشاء الجداول والمفاتيح الأساسية التلقائية.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
الاختصارات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 PHP PHP
- PHP: Hypertext Preprocessor
- لغة البرمجة النصية على جانب الخادم لبناء تطبيقات الويب الديناميكية وواجهات البرمجة.
- للمراجعة
- 02 CLI CLI
- Command-Line Interface
- واجهة سطر الأوامر التي تتيح تشغيل ملفات PHP مباشرة عبر الطرفية.
- للمراجعة
- 03 FPM FPM
- FastCGI Process Manager
- مدير عمليات FastCGI عالي الأداء لمعالجة طلبات خادم الويب في PHP.
- للمراجعة
- 04 HTML HTML
- HyperText Markup Language
- لغة الترميز القياسية التي يولدها محرك PHP ويرسلها إلى متصفح العميل بعد التنفيذ.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
مهامك قبل الاختبار
خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.
-
أنشئ ملف PHP محلياً ونفّذ المثال البرمجي المشروح في قسم تنفيذ أوامر الهيكلة عبر PDO::exec للتحقق من المخرجات.
-
بدّل بين الحالات الثلاث في المحاكي التفاعلي ضمن قسم إنشاء قاعدة بيانات بترميز UTF8MB4 وقارن مخرجات التنفيذ.
تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.
اختبر فهمك.
ووصلها للإتقان.
كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.
أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.
الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.
لمحة عن التحدي8 أسئلة تنتظرك +
ما دالة PDO المخصصة لتنفيذ أوامر الهيكلة (DDL) مثل CREATE TABLE التي لا تُرجع صفوف نتائج؟
تنفذ الدالة $pdo->exec($sql) الأمر مباشرة وتُرجع عدد الصفوف المتأثرة (0 لأوامر الهيكلة).
ما الترميز والمقارنة القياسية الواجب تحديدهما عند إنشاء قاعدة بيانات MySQL لدعم العربية والرموز ذات الـ 4 بايتات بالكامل؟
يدعم utf8mb4 محارف UTF-8 الكاملة ذات الـ 4 بايتات.
ما نوع عمود SQL الذي يجب استخدامه لتخزين أسعار المنتجات والأرصدة المالية بدقة؟
يخزن DECIMAL الأرقام العشرية بدقة تامة دون أخطاء التقريب الثنائي.
ما محرك التخزين المطلوب في MySQL لدعم المفاتيح الأجنبية (FOREIGN KEY) والمعاملات (Transactions)؟
يدعم محرك InnoDB المفاتيح الأجنبية والمعاملات وقفل الصفوف.
لماذا يجب فرض قيد UNIQUE (مثل البريد الإلكتروني) داخل جدول قاعدة البيانات نفسه وليس الاكتفاء بفحصه في كود PHP؟
فهرس UNIQUE في قاعدة البيانات هو الضمان الذري الوحيد لمنع التكرار تحت الضغط المتزامن.
ماذا يفعل الخيار ON DELETE CASCADE عند إضافته لتعريف المفتاح الأجنبي FOREIGN KEY (user_id) REFERENCES users(id)؟
يقوم CASCADE بحذف السجلات التابعة تلقائياً للحفاظ على التكامل المرجعي.
لماذا يُرجع PDO أعمدة DECIMAL(10, 2) كنصوص string في PHP (مثل "149.95") حتى عند تعطيل المحاكاة؟
الاحتفاظ بها كنص يحمي الأرقام المالية الدقيقة من أخطاء الفاصلة العائمة.
ما فائدة إضافة العبارة IF NOT EXISTS في الأمر CREATE TABLE IF NOT EXISTS users (...)؟
تتخطى إنشاء الجدول بسلام إذا كان موجوداً بالفعل دون إيقاف السكريبت.