الوظائف المتقدمة
لقد أتقنت أساسيات الدوال. يتيح لك هذا الدرس كتابة دوال أكثر مرونة وحداثة وتتماشى مع أسلوب PHP 8 — مثل المعلمات المتغيرة العدد، والحجج المسماة، والدوال السهمية — وكلها نتائج للتطور المستمر للغة PHP.
1. المعلمات المتغيرة العدد (...$args)
لا تعرف عدد المعلمات التي سيتم تمريرها؟ استخدم ... لتجميعها جميعًا في مصفوفة:
<?php
function sum(...$numbers): int {
return array_sum($numbers);
}
echo sum(1, 2); // 3
echo sum(1, 2, 3, 4, 5); // 15
echo sum(); // 0
// You can also have fixed parameters before the variadic ones
function sendMessage(string $to, string ...$messages): void {
foreach ($messages as $msg) {
echo "Sent to {$to}: {$msg}<br>";
}
}
sendMessage("John", "Good morning", "How's lunch?", "Good night");
// Sent to John: Good morning
// Sent to John: How's lunch?
// Sent to John: Good night
?>
▶ مثال: ... لتوزيع مصفوفة على المعلمات
<?php
function add(int $a, int $b, int $c): int {
return $a + $b + $c;
}
$nums = [1, 2, 3];
echo add(...$nums); // 6 (the array is spread into 3 separate arguments)
// Commonly used with array_push and similar functions
$stack = ["a", "b"];
array_push($stack, ...["c", "d", "e"]);
print_r($stack); // ["a", "b", "c", "d", "e"]
?>
تعمل ... في كلا الاتجاهين — ففي تعريف الدالة، تقوم بتجميع المعلمات في صفيف؛ أما في موقع الاستدعاء، فتقوم بتوزيع الصفيف على المعلمات.
2. المعلمات المسماة (PHP 8.0)
لا داعي لحفظ ترتيب المعلمات — قم بتمرير الحجج بالاسم:
▶ مثال: الحجج المسماة
<?php
function createUser(
string $name,
int $age,
string $email = "",
bool $isAdmin = false
): array {
return compact('name', 'age', 'email', 'isAdmin');
}
// Traditional: must follow parameter order
$u1 = createUser("John", 25, "john@example.com", true);
// Named arguments: order doesn't matter — skip parameters with defaults
$u2 = createUser(
name: "Jane",
age: 22,
isAdmin: true
// email uses the default
);
// When a function has many parameters, named arguments dramatically improve readability
setcookie(
name: "theme",
value: "dark",
expires_or_options: time() + 3600,
httponly: true
);
?>
createUser(name: "John", age: 25) واضحًا على الفور.
3. التمرير بالمرجع (&$var)
بشكل افتراضي، تقوم لغة PHP بتمرير معلمات الدالة بالقيمة — أي أن تعديل معلمة داخل الدالة لا يؤثر على المتغير الخارجي. أضف & للتمرير بالمرجع:
<?php
// Pass by value (default): internal modification doesn't affect the outside
function addTen(int $n): void {
$n += 10;
}
$x = 5;
addTen($x);
echo $x; // 5 (unchanged)
// Pass by reference: internal modification directly affects the outer variable
function addTenRef(int &$n): void {
$n += 10;
}
addTenRef($x);
echo $x; // 15 (changed!)
?>
| التمرير بالقيمة | التمرير بالمرجع | |
|---|---|---|
| بناء الجملة | function f($x) |
function f(&$x) |
| تعديل داخلي | لا يؤثر على المتغير الخارجي | يؤثر على المتغير الخارجي |
| الأنسب لـ | معظم الحالات | عندما تحتاج إلى «إرجاع» قيم متعددة |
sort(&$arr)).
4. نطاق المتغيرات
في لغة PHP، يُعد الجزء الداخلي للدالة والجزء الخارجي عالمين منفصلين:
<?php
$globalVar = "I'm outside";
function test(): void {
// echo $globalVar; // Warning: Undefined variable
// Functions can't directly access outer variables
$localVar = "I'm inside";
echo $localVar; // OK
}
test();
// echo $localVar; // Warning: can't access the function's inner variable either
?>
(1) استخدام «global» لكسر الحاجز
<?php
$counter = 0;
function increment(): void {
global $counter; // Declare: I want to use the global variable
$counter++;
}
increment();
increment();
echo $counter; // 2
?>
(2) المصفوفة الفائقة $GLOBALS
<?php
$name = "John";
function showName(): void {
echo $GLOBALS['name']; // John
}
showName();
?>
global هي «شر لا بد منه» — اعلم بوجودها، لكن تجنب استخدامها كلما أمكن ذلك. فالمتغيرات العالمية تجعل اختبار الكود وصيانته أمرًا صعبًا. وفي معظم الأحيان، قم بتمرير البيانات إلى الدوال كمعلمات.
5. المتغيرات الثابتة
المتغير static داخل الدالة يحتفظ بقيمته بين عمليات الاستدعاء:
<?php
function getNextId(): int {
static $id = 0;
$id++;
return $id;
}
echo getNextId(); // 1
echo getNextId(); // 2
echo getNextId(); // 3
// A static variable is only initialized once — on the first call
// Subsequent calls preserve the previous value
?>
6. الدوال المجهولة (الإغلاقات)
لا تحتاج الدوال إلى أسماء — يمكن تعيينها إلى متغيرات وتمريرها كمعاملات:
<?php
// Anonymous function assigned to a variable
$greet = function(string $name): string {
return "Hello, {$name}!";
};
echo $greet("John"); // Hello, John!
// Passed as an argument to another function (callback)
$numbers = [1, 2, 3, 4, 5];
$doubled = array_map(function($n) {
return $n * 2;
}, $numbers);
print_r($doubled); // [2, 4, 6, 8, 10]
?>
(1) استخدام الكلمة الرئيسية في الدوال المجهولة
إذا احتاجت دالة مجهولة إلى متغير خارجي، فيجب استيراده باستخدام use:
<?php
$prefix = "User";
// ❌ Wrong: $prefix is not visible inside the anonymous function
// $greet = function($name) {
// return "{$prefix}: {$name}";
// };
// ✅ Correct: import the outer variable with use
$greet = function($name) use ($prefix): string {
return "{$prefix}: {$name}";
};
echo $greet("John"); // User: John
// Import by reference (allows modifying the outer variable)
$count = 0;
$inc = function() use (&$count): void {
$count++;
};
$inc(); $inc();
echo $count; // 2
?>
7. دوال السهم (PHP 7.4+)
الدوال السهمية fn() => هي النسخة الموجزة للغاية من الدوال المجهولة ذات التعبير الواحد. فهي تلتقط المتغيرات الخارجية تلقائيًا (دون الحاجة إلى use):
<?php
$factor = 3;
// Anonymous function syntax
$anon = function($n) use ($factor) {
return $n * $factor;
};
// Arrow function syntax (automatically captures $factor)
$arrow = fn($n) => $n * $factor;
echo $anon(5); // 15
echo $arrow(5); // 15
// The golden pair with array_map
$nums = [1, 2, 3, 4, 5];
$tripled = array_map(fn($n) => $n * $factor, $nums);
print_r($tripled); // [3, 6, 9, 12, 15]
?>
map / filter / usort.
8. الدوال المرتدة ونوع «callable»
يتيح لك لغة PHP استخدام سلاسل أسماء الدوال، والدوال المجهولة، وطرق الكائنات كدوال استدعاء:
<?php
// Method 1: function name as a string
function double(int $n): int {
return $n * 2;
}
$result = array_map('double', [1, 2, 3]);
// 'double' (with quotes) — the function name string is passed to array_map
// Method 2: anonymous function
$result = array_map(fn($n) => $n * 3, [1, 2, 3]);
// Method 3: callable type declaration
function apply(callable $fn, array $data): array {
return array_map($fn, $data);
}
$result = apply('double', [1, 2, 3]); // ✅
$result = apply(fn($n) => $n * 2, [1, 2, 3]); // ✅
// apply(123, [1, 2, 3]); // TypeError!
?>
❓ أسئلة شائعة
... في لغة PHP؟...$args بتجميع الحجج المتبقية في صفيف. (2) عند استدعاء الدالة، يقوم ...$arr بتوزيع الصفيف إلى حجج فردية. sum(...$nums) تعني التوزيع؛ function sum(...$nums) تعني التجميع.foo(1, c: 3, b: 2) صحيحة؛ أما foo(a: 1, 2, 3) فهي غير صحيحة.fn($x) => $x * 2 للتعبيرات المفردة. واستخدم الدوال المجهولة function($x) { ... } للمنطق متعدد الأسطر. الدوال السهمية أكثر إيجازًا وتقوم بالتقاط المتغيرات الخارجية تلقائيًا (دون الحاجة إلى use).📖 ملخص
...$argsالمعلمات المتغيرة العدد: تجمع الوسيطات في صفيف / توزع محتويات الصفيف على الوسيطات- المعلمات المسماة (PHP 8):
fn(name: "John", age: 25)— تخطي المعلمات ذات القيم الافتراضية &$varالتمرير بالمرجع: الدالة تُعدِّل المتغير الخارجي (يُستخدم باعتدال)global/$GLOBALSللوصول إلى المتغيرات العالمية داخل الدوال- المتغير
static: يحتفظ بقيمته بين استدعاءات الدالة - الدوال المجهولة +
use: الدوال كمتغيرات - دوال السهم
fn() => expr: دوال استدعاء موجزة، والتقاط تلقائي للمتغيرات الخارجية
📝 تمارين
- اكتب دالة
average(...$numbers): floatتقبل أي عدد من المعاملات العددية وتُرجع متوسطها. - استخدم
array_mapودالة السهم لتحويل كل سلسلة في المصفوفة إلى أحرف كبيرة. - استخدم متغيرًا ثابتًا لكتابة دالة
hitCounter()تُرجع عدد الزيارات المتزايد عند كل استدعاء.



