Lesson 4 / الدرس 4

One structure that does almost everything / بنية واحدة تفعل كل شيء تقريبًا

PHP has one collection type where most languages have two, and it carries an enormous amount of the work. Learning the array and about a dozen functions that operate on it is most of learning the language.

في PHP نوع تجميع واحد حيث لمعظم اللغات نوعان، وهو يحمل قدرًا هائلًا من العمل. وتعلّم المصفوفة ونحو اثنتي عشرة دالة تعمل عليها هو معظم تعلّم اللغة.

In most languages a list and a dictionary are separate things. In PHP they are one thing called an array, which is a list when you give it no keys and a dictionary when you do. This is why PHP code reaches for arrays constantly — the content files for this entire site, every lesson you have read, are nested arrays and nothing else.

Both shapes, and moving between them

<?php
// A list: keys 0, 1, 2 are assigned for you.
$courses = ['Testing', 'Design', 'PHP'];
echo $courses[0];        // Testing
echo count($courses);    // 3

// A dictionary: you choose the keys.
$hours = ['testing' => 16, 'design' => 16, 'php' => 16];
echo $hours['php'];      // 16

// The same loop reads both. With a list you usually want the value;
// with a dictionary you usually want the key too.
foreach ($hours as $slug => $count) {
    echo "$slug takes $count hours\n";
}

// Nesting is where it gets useful. This is the shape of every
// content file on this site.
$lesson = [
    'slug'   => 'arrays',
    'blocks' => [
        ['type' => 'text',    'en' => 'In most languages…'],
        ['type' => 'heading', 'en' => 'Both shapes…'],
    ],
];
echo $lesson['blocks'][1]['en'];   // Both shapes…
The nested example is not a teaching toy. Open any file under content/ in this repository and you will find exactly that structure, a few hundred lines long. A whole content system can be arrays and files, with no database anywhere.

The dozen functions worth knowing by name

FunctionWhat it gives you
count($a)How many items
$a[] = $xAppend one item to the end
array_keys / array_valuesJust the keys, or just the values, renumbered
array_map($fn, $a)The same list with every item transformed
array_filter($a, $fn)Only the items that pass a test — keys are kept
array_column($a, "k")One field lifted out of a list of arrays
array_merge($a, $b)Two arrays joined
in_array / array_key_existsIs this value here / is this key here
array_sum($a)Everything added up
usort($a, $fn)Sorted by a rule you write

Almost every loop a beginner writes is one of these with more lines. Reach for the named function first: array_sum($hours) says what it is doing, while a four-line loop with a running total makes the reader work out that it is a sum.

<?php
// This site really does this, in src/Content.php, to build one flat
// list of lessons out of the chapters that hold them:
$lessons = array_merge([], ...array_column($course['chapters'], 'lessons'));

// Read it inside out:
//   array_column  lifts the 'lessons' list out of every chapter
//                 -> [['a','b'], ['c','d']]
//   ...           spreads that as separate arguments
//   array_merge   joins them  -> ['a','b','c','d']

// Filtering keeps keys. If you need a clean list afterwards, say so:
$long = array_values(array_filter($hours, fn($h) => $h > 12));
The second half of that comment is the part worth remembering: array_filter preserves keys, so filtering a list can leave you holding keys 0, 3 and 7. If the next thing you do is json_encode, that array becomes a JSON object instead of an array and something downstream breaks confusingly.

Check yourself / اختبر نفسك

1. What is the difference between a list and a dictionary in PHP?

2. You assign $b = $a where $a is an array, then append to $b. What is $a?

3. Why does array_filter sometimes cause a bug downstream?