في هذا الدرس 6تصفّح المواضيع
إن وضع معامل النقاط الثلاث (...$items) قبل اسم المعامل ينشئ دالة ذات معاملات متغيرة تقبل صفراً أو أكثر من القيم وتجمعها تلقائياً داخل مصفوفة.
- داخل جسم الدالة، يكون المتغير
$itemsمصفوفة PHP عادية مرقمة من الصفر تحتوي على كل القيم الممررة. - إذا لم يمرر المستدعي أي قيمة للمعامل المتغير، تكون قيمة
$itemsمصفوفة فارغة[]. - تُغني الصيغة الحديثة
...$itemsتماماً عن الدالة القديمةfunc_get_args().
يجمّع ...$prices كل الأرقام الممررة في مصفوفة واحدة لكي تحسب array_sum($prices) مجموعها أياً كان عددها.
<?php
function calculateTotal(...$prices) {
return array_sum($prices);
}
echo "3 items : " . calculateTotal(19.99, 5.01, 25.00) . "\n";
echo "0 items : " . calculateTotal() . "\n";
يمكن للدالة أن تشترط معاملات إلزامية ثابتة في البداية، ثم تلتقط جميع المعاملات الإضافية المتبقية في معامل متغير واحد يوضع في آخر قائمة المعاملات.
- يُسمح فقط للمعامل الأخير في تعريف الدالة أن يكون متغيراً (
function logLine($level, ...$messages)). - إن وضع أي معامل آخر بعد
...$messagesيسبب خطأً فادحاً وقت الترجمة (Compile Error). - يضمن هذا النمط تزويد المعاملات الأساسية الإلزامية دائماً مع إبقاء عدد العناصر الإضافية مرناً.
يرتبط المعامل الأول "env" بالمتغير الثابت $prefix، بينما تُحزم القيم الثلاث المتبقية داخل المصفوفة $tags.
<?php
function buildTagList($prefix, ...$tags) {
$formatted = [];
foreach ($tags as $tag) {
$formatted[] = $prefix . ":" . strtolower($tag);
}
return implode(", ", $formatted);
}
echo buildTagList("env", "Prod", "EU-West", "PHP84") . "\n";
عند استدعاء دالة، يؤدي وضع النقاط الثلاث ... قبل متغير المصفوفة إلى تفكيك عناصرها وتمرير كل عنصر كمعامل مستقل.
- في تعريف الدالة يقوم
...$argsبتجميع المعاملات في مصفوفة؛ أما عند استدعاء الدالة فيقوم...$arrبتفكيك المصفوفة إلى معاملات منفردة. - في PHP 8.0+، يؤدي تفكيك مصفوفة ترابطية عند الاستدعاء إلى تمرير مفاتيحها النصية كمعاملات مسماة تطابق أسماء معاملات الدالة!
- يغني تفكيك المعاملات بـ
...عن الدالة القديمةcall_user_func_array()بصيغة أسرع وأوضح.
يفكك ...$indexed القيم حسب الترتيب، بينما يطابق ...$named المفاتيح النصية مع أسماء معاملات الدالة مباشرة.
<?php
function createServerUrl($host, $port, $scheme) {
return "$scheme://$host:$port";
}
$indexed = ["api.closetag.com", 8443, "https"];
$named = ["port" => 9000, "scheme" => "http", "host" => "localhost"];
echo createServerUrl(...$indexed) . "\n";
echo createServerUrl(...$named) . "\n";
افتراضياً يمرر PHP المتغيرات والمصفوفات بالقيمة. أما وضع الرمز (&$param) فيربط المعامل بالمتغير الأصلي للمستدعي بحيث يستمر أي تعديل خارج الدالة.
- لا يمكن تمرير سوى متغيرات فعلية (مثل
$counter) إلى معامل بالمرجع؛ وتمرير قيمة ثابتة مثلincrement(5)يطلق خطأً فادحاً. - تستخدم دوال PHP المدمجة مثل
sort(&$array)وarray_splice(&$array, ...)التمرير بالمرجع لتعديل المصفوفة في مكانها. - في الكود الحديث، يُفضل إرجاع القيمة الجديدة عبر
returnبدلاً من التعديل بالمرجع كلما أمكن ليكون مسار البيانات أوضح.
لأن &$price مُمرر بالمرجع، فإن طرح الخصم يحدّث قيمة المتغير الأصلي $cartSubtotal خارج الدالة إلى 170.
<?php
function applyDiscount(&$price, $percent) {
$discount = $price * ($percent / 100);
$price -= $discount;
return $discount;
}
$cartSubtotal = 200.00;
$saved = applyDiscount($cartSubtotal, 15);
echo "Saved: $$saved | New Subtotal: $$cartSubtotal\n";
في PHP، إذا كان المتغير يحمل اسماً نصياً لدالة وأتبعته بقوسين $fn()، يقوم PHP بالبحث عن تلك الدالة وتنفيذها ديناميكياً.
- تحقق دائماً من وجود الدالة باستخدام
function_exists($fn)أوis_callable($fn)قبل استدعائها عبر$fn(). - بنى اللغة الأساسية مثل
echoوissetوemptyوunsetوincludeليست دوال ولا يمكن استدعاؤها كدوال متغيرة. - لا تنفذ أبداً نصاً قادماً من المستخدم كدالة متغيرة مباشرة؛ بل احصر الاستدعاءات في قائمة بيضاء محددة مسبقاً.
تتحقق function_exists($operation) من توفر الدالة strtoupper قبل أن يستدعيها التعبير $operation($input) ديناميكياً.
<?php
$operation = "strtoupper";
$input = "closetag php 8.4";
if (function_exists($operation)) {
echo "Result: " . $operation($input) . "\n";
}
echo "mb_strlen available? " . (function_exists("mb_strlen") ? "Yes" : "No") . "\n";
بدءاً من PHP 8.1، تتيح كتابة ثلاث نقاط داخل قوسي الدالة مثل strlen(...) أو trim(...) إنشاء مرجع مباشر للدالة يدعم الإكمال التلقائي في المحررات بدلاً من كتابة اسمها كنص.
- على عكس كتابة اسم الدالة كنص (
"trim")، تخضع صيغةtrim(...)للفحص الثابت وتدعم إعادة التسمية الآمنة في بيئات التطوير. - لاحظ الفرق الدقيق: كتابة
myFunc(...$arr)تستدعي الدالة فوراً بتفكيك المصفوفة، بينما كتابةmyFunc(...)لا تستدعيها بل ترجع كائنClosureيشير إليها. - مرر هذا المرجع مباشرة إلى دوال مثل
array_map(trim(...), $inputs).
تلتقط formatSku(...) إشارة مرجعية للدالة داخل $formatter دون تنفيذها، ثم تطبقها array_map() على كل عنصر.
| الصيغة | المصطلح | السلوك البرمجي |
|---|---|---|
function f(...$a) | معامل متغير الطول (Variadic) | يجمع الوسائط الممررة داخل مصفوفة $a |
f(...$arr) | تفكيك المصفوفة عند الاستدعاء | يفكك عناصر $arr كوسائط مستقلة للدالة |
function f(&$x) | التمرير بالمرجع (By Reference) | يعدّل المتغير الأصلي $x مباشرة |
$fn($arg) | دالة متغيرة (Variable Function) | يستدعي الدالة التي يحمل المتغير النصي $fn اسمها |
f(...) | مرجع دالة من الدرجة الأولى (8.1+) | يرجع كائن Closure يشير إلى الدالة f دون تنفيذها |
<?php
function formatSku($raw) {
return "SKU-" . strtoupper(trim($raw));
}
$formatter = formatSku(...);
$items = [" kb90 ", " ms20 "];
$mapped = array_map($formatter, $items);
echo implode(" | ", $mapped) . "\n";
ملخص الدرس
حصاد الدرسمراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي
ماذا تعلّمت في هذا الدرس؟
بدءاً من PHP 8.1، تتيح كتابة ثلاث نقاط داخل قوسي الدالة مثل strlen(...) أو trim(...) إنشاء مرجع مباشر للدالة يدعم الإكمال التلقائي في المحررات بدلاً من كتابة اسمها كنص. على عكس كتابة اسم الدالة كنص ("trim")، تخضع صيغة trim(...) للفحص الثابت وتدعم إعادة التسمية الآمنة في بيئات التطوير. لاحظ الفرق الدقيق: كتابة myFunc(...$arr) تستدعي الدالة فوراً بتفكيك المصفوفة، بينما كتابة myFunc(...) لا تستدعيها بل ترجع كائن Closure يشير إليها. مرر هذا المرجع مباشرة إلى دوال مثل array_map(trim(...), $inputs).
سجّل الدخول لحفظ تقدمك
تابع إنجاز المواضيع والمصطلحات والمهام، وكمّل من آخر خطوة على أي جهاز.
المصطلحات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 Variadics & Unpacking المعاملات المتغيرة ...$args
- استقبل عدداً مرناً من المعاملات عبر معامل التجميع (...$args)، وفكك المصفوفات عند الاستدعاء، وتحقق من وجود الدوال بـ function_exists.
- للمراجعة
- 02 Collecting Arguments with Variadic Splat تجميع المعاملات المتغيرة في مصفوفة عبر ...$args
- المفهوم الأساسي لقسم تجميع المعاملات المتغيرة في مصفوفة عبر ...$args في لغة PHP الحديثة.
- للمراجعة
- 03 Combining Fixed and Variadic Parameters دمج المعاملات الإلزامية مع المعامل المتغير الأخير
- الصياغة البرمجية والتطبيق العملي المباشر لقسم دمج المعاملات الإلزامية مع المعامل المتغير الأخير.
- للمراجعة
- 04 Unpacking Arrays into Function Arguments تفكيك عناصر المصفوفة وتمريرها عند استدعاء الدالة
- قواعد التحقق وأفضل الممارسات القياسية الخاصة بقسم تفكيك عناصر المصفوفة وتمريرها عند استدعاء الدالة.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
الاختصارات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 محلياً ونفّذ المثال البرمجي المشروح في قسم تجميع المعاملات المتغيرة في مصفوفة عبر ...$args للتحقق من المخرجات.
-
بدّل بين الحالات الثلاث في المحاكي التفاعلي ضمن قسم دمج المعاملات الإلزامية مع المعامل المتغير الأخير وقارن مخرجات التنفيذ.
تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.
اختبر فهمك.
ووصلها للإتقان.
كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.
أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.
الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.
لمحة عن التحدي8 أسئلة تنتظرك +
أين يجب وضع المعامل المتغير (...$items) في قائمة معاملات الدالة في PHP؟
يُسمح للمعامل الأخير فقط أن يكون متغيراً ليعرف PHP أين تنتهي المعاملات الثابتة.
ما نوع البيانات للمتغير $numbers داخل الدالة function sum(...$numbers) عند استدعائها بدون معاملات sum()؟
يكون المعامل المتغير مصفوفة دائماً، وعند عدم تمرير قيم يكون مصفوفة فارغة [].
ماذا يحدث في PHP 8+ عند تفكيك مصفوفة ترابطية في استدعاء الدالة: calc(...["tax" => 5, "price" => 100])؟
في PHP 8.0+ ترتبط المفاتيح النصية عند التفكيك بأسماء المعاملات مباشرة.
كيف تعرّف معاملاً بحيث يؤدي تعديله داخل الدالة إلى تعديل المتغير الأصلي لدى المستدعي؟
يمرر الرمز & المعامل بالمرجع بدلاً من القيمة المستقلة.
ماذا يحدث إذا استدعيت دالة تستقبل معاملاً بالمرجع ومررت لها رقماً مباشراً مثل increment(10)؟
القيمة الثابتة مثل 10 ليست متغيراً قابلاً للتعديل بالمرجع.
أي دالة تتحقق مما إذا كان اسم الدالة المخزن في $fn معرّفاً وموجوداً قبل استدعائه عبر $fn()؟
ترجع function_exists() القيمة true إذا كانت الدالة المدمجة أو المخصصة معرفة.
لماذا يفشل الكود $fn = "echo"; $fn("Hello"); ويطلق خطأً فادحاً؟
البنى اللغوية مثل echo وisset وempty لا يمكن استدعاؤها كدوال متغيرة.
ماذا ترجع الصيغة strlen(...) (ثلاث نقاط داخل القوسين) في PHP 8.1+؟
تنشئ صيغة fnName(...) كائن Closure يمثل مرجعاً للدالة.