PHP: Видимость переменных (scope)
Видимость переменных в PHP
Glossary overview

PHP: Видимость переменных (scope)

В PHP переменные обычно живут в пределах функции. Это называется function scope.
Если переменная создана внутри функции, она доступна везде внутри этой функции, даже если она появилась внутри for, if, while.

function test() {
    if (true) {
        $x = 123;
    }
    echo $x; // 123, потому что if не создает отдельный scope
}

В PHP нет “блочной видимости” как в JS. В JS (с let/const) есть block scope:

// JS

if (true) {
  let x = 1;
}
console.log(x); // ошибка

В PHP такого нет:

// PHP

if (true) {
    $x = 1;
}
echo $x; // 1

Вот пример с моего кода:

<?php

function mergeTwoSortedArrays(array $arr1, array $arr2): array {
    $merged = [];
    $n1 = count($arr1);
    $n2 = count($arr2);

    // i и j объявлены внутри for
    for ($i = 0, $j = 0; $i < $n1 && $j < $n2; ) {
        if ($arr1[$i] <= $arr2[$j]) {
            $merged[] = $arr1[$i];
            $i++;
        } else {
            $merged[] = $arr2[$j];
            $j++;
        }
    }

    // Мы тут имеем доступ к $i, хотя определили его в for

    // добиваем хвост arr1
    for (; $i < $n1; $i++) {
        $merged[] = $arr1[$i];
    }

    // добиваем хвост arr2
    for (; $j < $n2; $j++) {
        $merged[] = $arr2[$j];
    }

    return $merged;
}

// Пример:
$array1 = [1, 3, 5, 7];
$array2 = [2, 4, 6, 8, 10];
print_r(mergeTwoSortedArrays($array1, $array2));

$array3 = [10, 20, 30];
$array4 = [5, 15];
print_r(mergeTwoSortedArrays($array3, $array4));

Почему в твоем коде виден $i во втором for.
Потому что $i был создан в первом for и остался в том же scope функции.

for ($i = 0; $i < 3; $i++) {}
// тут $i существует и равен 3

for (; $i < 10; $i++) {}

Но есть “блоки”, которые реально создают свой scope
Вот тут уже люди путаются. В PHP отдельный scope появляется не у if/for, а у:

    • функций
    • анонимных функций (closures)
    • методов класса

    Пример:

    // No
    
    $x = 10;
    
    $fn = function () {
        // echo $x; // так нельзя напрямую
    };
    
    $fn();
    
    
    // Yes
    $x = 10;
    
    $fn = function () use ($x) {
        echo $x; // 10
    };
    
    $fn();

    Важный момент для циклов: переменная “протекает” дальше
    Побочный эффект PHP: после цикла переменная остается.

    for ($i = 0; $i < 2; $i++) {}
    echo $i; // 2