PHP: مشروع تدريبي — المصفوفات والدوال
آخر تحديث: 2026-08-26
لقد أمضيت 14 درسًا في استيعاب قواعد اللغة والوظائف. حان الوقت الآن لربط كل هذه العناصر معًا. ستتيح لك هذه المشاريع الثلاثة — التي تتراوح بين البسيطة والطموحة — إنشاء تطبيقات PHP حقيقية وقابلة للتشغيل.
1. الإعداد
أنشئ مجلدًا باسم practice/ داخل الدليل htdocs/myphp/ وضع جميع ملفات التمارين فيه. يمكنك الوصول إليها من خلال http://localhost/myphp/practice/.
2. المشروع الأول: عربة التسوق
صمم نموذجًا لعربة التسوق باستخدام مصفوفة — أضف العناصر، وقم بتحديث الكميات، وأزل العناصر، واحسب الإجماليات.
<?php
// cart.php — Shopping Cart System
/**
* Add an item to the cart
* @param array $cart Cart array (by reference)
* @param string $name Product name
* @param float $price Unit price
* @param int $qty Quantity (default: 1)
* @return void
*/
function addItem(array &$cart, string $name, float $price, int $qty = 1): void {
if (isset($cart[$name])) {
$cart[$name]['qty'] += $qty;
} else {
$cart[$name] = ['price' => $price, 'qty' => $qty];
}
}
/**
* Update a product's quantity
*/
function updateQty(array &$cart, string $name, int $qty): void {
if ($qty <= 0) {
unset($cart[$name]);
} elseif (isset($cart[$name])) {
$cart[$name]['qty'] = $qty;
}
}
/**
* Remove an item from the cart
*/
function removeItem(array &$cart, string $name): void {
unset($cart[$name]);
}
/**
* Calculate the total price
*/
function getTotal(array $cart): float {
return array_sum(array_map(
fn($item) => $item['price'] * $item['qty'],
$cart
));
}
// === Test the cart ===
$cart = [];
addItem($cart, "PHP Tutorial", 39.90, 2);
addItem($cart, "MySQL Basics", 29.90, 1);
addItem($cart, "PHP Tutorial", 39.90, 1); // Add one more copy
echo "<pre>";
echo "Cart contents:\n";
print_r($cart);
echo "\nTotal: $" . getTotal($cart) . "\n";
// Update quantity
updateQty($cart, "MySQL Basics", 3);
echo "\nAfter update — Total: $" . getTotal($cart) . "\n";
// Remove an item
removeItem($cart, "PHP Tutorial");
echo "\nAfter removal:\n";
print_r($cart);
echo "\nFinal total: $" . getTotal($cart) . "\n";
echo "</pre>";
?>
3. المشروع الثاني: قائمة المهام
إدارة المهام باستخدام مصفوفة — الإضافة، والإنجاز، والحذف، والتصفية حسب الحالة، والفرز حسب الأولوية.
▶ مثال: تطبيق «Todo»
<?php
// todo.php — To-Do List
/**
* Add a new task
*/
function addTodo(array &$todos, string $title, string $priority = "medium"): void {
$todos[] = [
'id' => count($todos) + 1,
'title' => $title,
'done' => false,
'priority' => $priority,
'created' => date("Y-m-d H:i:s"),
];
}
/**
* Mark a task as complete
*/
function markDone(array &$todos, int $id): void {
foreach ($todos as &$todo) {
if ($todo['id'] === $id) {
$todo['done'] = true;
break;
}
}
}
/**
* Delete a task
*/
function deleteTodo(array &$todos, int $id): void {
$todos = array_filter($todos, fn($t) => $t['id'] !== $id);
}
/**
* Get all pending (incomplete) tasks
*/
function getPending(array $todos): array {
return array_filter($todos, fn($t) => !$t['done']);
}
/**
* Completion statistics
*/
function getStats(array $todos): array {
$total = count($todos);
$done = count(array_filter($todos, fn($t) => $t['done']));
return ['total' => $total, 'done' => $done, 'pending' => $total - $done];
}
// === Test the Todo app ===
$todos = [];
addTodo($todos, "Learn PHP arrays", "high");
addTodo($todos, "Practice foreach loops", "medium");
addTodo($todos, "Write the cart functions", "high");
addTodo($todos, "Review date functions", "low");
markDone($todos, 1);
markDone($todos, 3);
$stats = getStats($todos);
echo "Total: {$stats['total']} | Done: {$stats['done']} | Pending: {$stats['pending']}<br>";
echo "<h3>Pending Tasks</h3>";
foreach (getPending($todos) as $todo) {
$priorityEmoji = [
'high' => '🔴',
'medium' => '🟡',
'low' => '🟢',
];
echo $priorityEmoji[$todo['priority']] . " {$todo['title']}<br>";
}
?>
4. المشروع الثالث: استطلاع بسيط
استخدم مصفوفة ترابطية لتخزين الخيارات وعدد الأصوات، مع توفير إمكانية التصويت وعرض النتائج والفرز حسب عدد الأصوات.
▶ مثال: نظام التصويت
<?php
// vote.php — Simple Poll
function createPoll(array $options): array {
return array_fill_keys($options, 0);
}
function vote(array &$poll, string $option): bool {
if (!array_key_exists($option, $poll)) {
return false;
}
$poll[$option]++;
return true;
}
function getResults(array $poll): array {
arsort($poll); // Sort by vote count descending
return $poll;
}
function getTotalVotes(array $poll): int {
return array_sum($poll);
}
function getWinner(array $poll): ?string {
$results = getResults($poll);
$maxVotes = max($results);
if ($maxVotes === 0) return null;
return array_key_first($results);
}
// === Test the poll ===
$poll = createPoll(["PHP", "Python", "JavaScript", "Go", "Rust"]);
vote($poll, "PHP");
vote($poll, "PHP");
vote($poll, "JavaScript");
vote($poll, "Python");
vote($poll, "PHP");
vote($poll, "Rust");
vote($poll, "Python");
echo "<h3>Poll Results</h3>";
echo "Total votes: " . getTotalVotes($poll) . "<br>";
$results = getResults($poll);
foreach ($results as $lang => $votes) {
$percent = round($votes / getTotalVotes($poll) * 100, 1);
$bar = str_repeat("█", $votes);
echo "{$lang}: {$bar} {$votes} vote(s) ({$percent}%)<br>";
}
echo "<br>🏆 Leader: " . getWinner($poll) . "<br>";
?>
5. التأمل: من البرامج النصية إلى التطبيقات
تُبرز هذه المشاريع الثلاثة عدة أفكار رئيسية:
- المصفوفات لا تقتصر على تخزين البيانات فحسب — بل يمكنها أيضًا تمثيل منطق الأعمال الفعلي.
- الدوال تعمل على تغليف العمليات، مما يضمن بقاء الكود نظيفًا وقابلًا للتركيب.
- التمرير بالمرجع (
&$arr) يتيح للدوال تعديل هياكل البيانات مباشرةً. array_map+ الدوال السهمية تجعل معالجة البيانات موجزة وسهلة القراءة.
لكنك ربما لاحظت أيضًا أوجه القصور التالية:
- تُخزَّن جميع البيانات في الذاكرة — وتُحذف عند تحديث الصفحة. (تم حل هذه المشكلة لاحقًا باستخدام الجلسات / قواعد البيانات.)
- يختلط الكود مع العرض. (تم حل هذه المشكلة لاحقًا باستخدام بنية MVC.)
- لا يوجد تفاعل مع النماذج حتى الآن. (هذا موضوع الدرس التالي.)
❓ أسئلة شائعة
array_fill_keys؟array_fill_keys(['a', 'b'], 0) تُرجع ['a' => 0, 'b' => 0] — فهي تُعيّن نفس القيمة لعدة مفاتيح في استدعاء واحد. نستخدمها في نظام الاستطلاع لتهيئة كل خيار بحيث يكون عدد الأصوات عليه صفرًا.📖 ملخص
- سلة التسوق: المصفوفات الترابطية + التمرير بالمرجع + تتبع الكمية
- قائمة المهام: المصفوفات متعددة الأبعاد +
array_filterللتصفية + الإحصاءات - استطلاع الرأي:
array_fill_keysللتعيين الأولي +arsortللترتيب +array_key_first - إن فهم القيد المتمثل في "عدم وجود حالة" يبرز الحاجة إلى الجلسات وقواعد البيانات
📝 تمارين
- قم بتوسيع سلة التسوق لتشمل 5 منتجات على الأقل، ثم أضف وظيفة
clearCart()التي تعمل على إزالة كل المحتويات. - إضافة خيار «الترتيب حسب الأولوية» (عالية ← متوسطة ← منخفضة) إلى نظام قائمة المهام.
- إضافة آلية لمنع التزوير في الاقتراع: التحقق من وجود الخيار قبل احتساب الصوت، ورفض الخيارات غير الصالحة.