Lesson 5 / الدرس 5
Naming a piece of work / تسمية قطعة عمل
A function is the smallest unit you can name, test and trust. The discipline that matters is not writing them — it is making each one depend only on what it was given, so that reading its first line tells you everything it can touch.
الدالة أصغر وحدة تستطيع تسميتها واختبارها والوثوق بها. والانضباط المهم ليس كتابتها — بل جعل كلٍّ منها تعتمد على ما أُعطيته فقط، حتى تخبرك قراءة سطرها الأول بكل ما تستطيع مسّه.
You met functions in the basics course. PHP adds one thing worth taking seriously: you can declare what goes in and what comes out, and PHP will enforce it. A typed signature is documentation that cannot go stale, because the code stops working when it becomes untrue.
<?php
declare(strict_types=1); // first line of every file on this site
function hours(array $course): int
{
return array_sum(array_column($course['chapters'], 'hours'));
}
// Optional arguments have defaults, and go last.
function summary(string $text, int $limit = 120): string
{
return strlen($text) <= $limit
? $text
: substr($text, 0, $limit - 1) . '…';
}
// ?string means 'a string or null'. Being explicit about null is
// most of what type declarations buy you.
function findCourse(array $all, string $slug): ?array
{
return $all[$slug] ?? null;
}
declare(strict_types=1) is what makes those declarations mean anything. Without it PHP quietly converts "16" to 16 for you; with it, passing a string where an int was declared is an error at the call. Put it at the top of every file — every file in this repository has it. declare(strict_types=1) هي ما يجعل تلك الإعلانات تعني شيئًا. فبدونها تحوّل PHP "16" إلى 16 لك بهدوء؛ ومعها يكون تمرير نص حيث أُعلن عدد صحيح خطأً عند الاستدعاء. ضعها في أعلى كل ملف — فكل ملف في هذا المستودع فيه.A function should not reach outside itself
<?php
// Bad. This function reads $_POST directly.
function saveSubmission(): void
{
$title = $_POST['title'];
// …
}
// Good. Everything it uses arrives through the door.
function saveSubmission(string $title, int $studentId): void
{
// …
}
// The caller does the reaching, once, where you can see it:
saveSubmission($_POST['title'] ?? '', $user['id']);
Small closures, for the array functions
-
fn($x) => $x * 2— the short form. One expression, and it can see the variables around it automatically. This is what you pass toarray_mapandarray_filter.fn($x) => $x * 2— الصيغة القصيرة. تعبير واحد، وترى المتغيرات حولها تلقائيًا. وهذا ما تمرّره إلىarray_mapوarray_filter. -
function ($x) use ($limit) { … }— the long form, for more than one statement. It sees nothing from around it unless you list it inuse, which catches a whole class of mistake.function ($x) use ($limit) { … }— الصيغة الطويلة، لأكثر من عبارة. وهي لا ترى شيئًا مما حولها إلا إن أدرجته فيuse، وهذا يلتقط صنفًا كاملًا من الخطأ. -
If a closure grows past about three lines, it wanted a name. Give it one and call it —
usort($courses, byTitle(...))reads better than five anonymous lines wedged inside a call.وإن نما إغلاق فوق ثلاثة أسطر تقريبًا، فقد كان يريد اسمًا. فأعطه واحدًا واستدعه — فـusort($courses, byTitle(...))تُقرأ خيرًا من خمسة أسطر مجهولة محشورة داخل استدعاء.
global وينبغي ألا تظهر في كود تكتبه. فالدالة التي تستخدم global $db تعتمد على شيء لا يراه قارئ من توقيعها، وتنكسر لحظة استدعائها من ملف آخر، ولا يمكن اختبارها البتة. وكل حجة لصالح متغير عام هي في الحقيقة حجة لتمرير وسيط واحد إضافي، يكلّف كلمة ويشتري القدرة على رؤية ما تمسّه الدالة.hours($course) لا calculateSumOfChapterHours($course). فالاسم يُقرأ مئة ضعف قراءة الجسم، ولا يهم المستدعيَ أن في داخلها حلقة.Check yourself / اختبر نفسك
1. What does declare(strict_types=1) change?
Without it, passing "16" to a function expecting int quietly becomes 16, and the declaration is decoration. With it the declaration is a check, which is what makes a typed signature documentation that cannot go stale.
2. Why should a function take $_POST values as arguments rather than reading $_POST itself?
A function that reaches outside itself cannot be called with values you made up, which is exactly what a test does. This is the same argument the testing course made about what makes code testable at all.
3. What is wrong with global $db inside a function?
Every argument for a global is an argument for one more parameter. The parameter costs a word and makes what the function touches visible to anyone reading its first line.
Score / النتيجة: 0 / 3