← Lekcje
PHP · lekcja 10

Funkcje 3/3: zmienne lokalne

Dzisiaj sprawdzacie, co funkcja w ogóle widzi:

  1. Dwa zamknięte „pokoje”: zmienne poza funkcjami i zmienne wewnątrz funkcji
  2. Pętla while z akumulatorem, który żyje tylko wewnątrz funkcji
  3. Co się dzieje, gdy spróbujecie użyć takiej zmiennej na zewnątrz?
  4. Ćwiczenie: sumUpTo($upTo) w functions.php
Rozgrzewka · 3 minuty

Rozgrzewka: argumenty z poprzedniej lekcji

function greetUser($name, $language = "pl") {
    if ($language === "en") {
        return "Hello, $name!";
    }
    return "Cześć, $name!";
}
  1. Co wypisze echo greetUser("Kasia");?
  2. Dlaczego greetUser() bez żadnego argumentu rzuci błąd?
  3. Gdyby ktoś w środku funkcji zmienił wartość $name, czy zmieniłaby się zmienna użyta przy wywołaniu?
Część 1 · Zasięg zmiennej

Dwa zamknięte „pokoje”

zasięg globalny (poza funkcjami) $counter = 100 wnętrze funkcji sumUpTo $sum $i mur bez „global” nic tędy nie przejdzie

Obszar kodu, w którym zmienna istnieje i można jej używać, nazywa się zasięgiem zmiennej. Zmienna zadeklarowana wewnątrz funkcji ma zasięg tylko w jej „pokoju”. Przez mur między pokojami nic nie przechodzi samo, poza dwoma wyjątkami, które już znacie: parametr (wejście) i return (wyjście).

PHP Manual: „The scope of a variable is the context within which it is defined... Any variable created inside a named function or an anonymous function is limited to the scope of the function body” · php.net/manual/en/language.variables.scope.php
Część 2 · Akumulator wewnątrz funkcji

Pętla while z akumulatorem

$sum to akumulator: zmienna, która zbiera wynik po trochu, przy każdym obiegu pętli.

function sumUpTo($upTo) {
    $sum = 0;
    $i = 1;
    while ($i <= $upTo) {
        $sum += $i;
        $i++;
    }
    return $sum;
}

echo sumUpTo(5);
$i $sum po $sum += $i 10 + 1 = 1 21 + 2 = 3 33 + 3 = 6 46 + 4 = 10 510 + 5 = 15 6 6 <= 5 fałsz, pętla stop return $sum; → 15
Część 2 · Ta sama nazwa nie znaczy ta sama zmienna

Ta sama nazwa, różne zmienne

$counter = 100;

function localCounter() {
    $counter = 5;
    echo $counter . "<br>";
}

localCounter();
echo $counter . "<br>";

Wynik w przeglądarce: 5, potem 100. Funkcja miała swój własny $counter w swoim pokoju; ten na zewnątrz nawet o tym nie wie.

PHP Manual: „This is because the [variable] refers to a local version... it has not been assigned a value within this scope” · php.net/manual/en/language.variables.scope.php
Część 3 · Próba wejścia przez mur

Zmienna z wnętrza funkcji poza nią nie istnieje

function sumUpTo($upTo) {
    $sum = 0;
    $i = 1;
    while ($i <= $upTo) {
        $sum += $i;
        $i++;
    }
    return $sum;
}

echo sumUpTo(5) . "<br>";
echo $sum . "<br>";  // $sum tu nie istnieje
echo $sum; mur funkcji sumUpTo Warning: Undefined variable $sum $sum żyło tylko w czasie działania funkcji

Ciekawostka z PHP Manual: to nie zawsze prawda. Słowo static przed deklaracją zmiennej w funkcji sprawia, że taka zmienna zapamiętuje swoją wartość między kolejnymi wywołaniami tej samej funkcji, zamiast znikać po każdym powrocie z return.

ciekawostka: PHP Manual, „A static variable exists only in a local function scope, but it does not lose its value when program execution leaves this scope” · php.net/manual/en/language.variables.scope.php
Część 4 · Zanim zawołasz o pomoc

Typowe pułapki zasięgu

SytuacjaCo się dziejePoprawka
Odczyt zmiennej z wnętrza funkcji na zewnątrz (echo $sum; po sumUpTo(5))Warning: Undefined variable $sum - zmienna zniknęła razem z końcem funkcjiPotrzebny wynik zwróćcie przez return i zapiszcie do zmiennej: $result = sumUpTo(5);
Odczyt zmiennej globalnej wewnątrz funkcji bez niczego więcejWarning: Undefined variable $counter - funkcja domyślnie nie widzi tego, co jest poza niąSłowo kluczowe global $counter; na początku funkcji „wpuszcza” zmienną globalną do środka
Ta sama nazwa zmiennej globalnie i wewnątrz funkcjiZmiana jednej nie rusza drugiej - to dwie osobne zmienne o wspólnej nazwieNie ma poprawki - to normalne działanie zasięgu, nazwa nie tworzy związku
PHP Manual: „The global keyword is used to bind a variable from a global scope into a local scope” · php.net/manual/en/language.variables.scope.php
Egzamin INF.03

Tak pytają na egzaminie

function calculate($Z) {
    while($Z < 5) {
        $Z += 2 * $Z + 1;
    }
    return $Z;
}

1. Zapisaną językiem PHP funkcję o nazwie calculate wywołano z argumentem $Z = 1. Jaki wynik zostanie zwrócony?

  1. 13
  2. 7
  3. 4
  4. 1
if($a > $b && $a > $c) echo $a;
elseif($b > $c) echo $b;
else echo $c;

2. Zakładając, że zmienne $a, $b, $c przechowują wartości numeryczne, wynikiem działania warunku będzie wypisanie liczby

  1. najmniejszej
  2. największej
  3. nieparzystej
  4. parzystej
CKE, EE.09, styczeń 2021, zadanie 8 · CKE, E.14, wrzesień 2015, zadanie 29
Ćwiczenie przy komputerze · 20 minut

Ćwiczenie: sumUpTo()

  1. W swoim functions.php dopisz funkcję sumUpTo($upTo): $sum = 0, $i = 1, pętla while ($i <= $upTo) z $sum += $i; i $i++;, na końcu return $sum;.
  2. Wywołaj echo sumUpTo(5) . "<br>"; - ma pojawić się 15.
  3. Zaraz pod tym dopisz na chwilę echo $sum; (poza funkcją) i sprawdź, że $sum tam nie istnieje (Warning: Undefined variable). Potem usuń tę linię.
  4. Sprawdź w przeglądarce pod localhost/functions.php, potem zostaw plik w folderze kursu.

Ma się pojawić: 15 obok wyników squareArea i greetUser z poprzednich lekcji. Ostrzeżenie Undefined variable widzicie tylko w punkcie 3, potem je usuwacie.

Dla szybkich: dopiszcie w sumUpTo linię global $totalResult; i $totalResult = $sum; przed return. Sprawdźcie, że teraz echo $totalResult; na zewnątrz już działa.

Zasady pracowni
Na koniec

Sprawdź się

  1. Czym różni się zmienna zdefiniowana wewnątrz funkcji od zmiennej zdefiniowanej poza funkcjami?
  2. Co się stanie, gdy poza funkcją spróbujecie użyć zmiennej, która istnieje tylko w jej wnętrzu?
  3. Czy zmienna globalna i zmienna wewnątrz funkcji o tej samej nazwie to jedna i ta sama zmienna?

To zamyka temat funkcji własnych: parametry i return, argumenty i wartości domyślne, zmienne lokalne.

Poza szkołą

A jak to wygląda w produkcji?

Na lekcjiW produkcjiStatus
Zmienne lokalne widoczne tylko wewnątrz jednej funkcjiDane zamykane we właściwościach obiektu ($this->sum) zamiast luźnych zmiennych - kolejny krok po funkcjach, po temacie klas i obiektów.nadal w użyciu
Słowo global wpuszczające zmienną globalną do funkcjiW praktyce prawie nieużywane - dane wchodzą przez parametr, wychodzą przez return, tak jak na poprzednich dwóch lekcjach; global utrudnia śledzenie, skąd bierze się wartość.unikane
Komunikat Warning: Undefined variable widoczny dopiero w przeglądarceEdytor i narzędzia do statycznej analizy kodu (np. PHPStan) wypisują ten sam błąd, zanim kod w ogóle się uruchomi.nadal w użyciu
PHP Manual: language.variables.scope.php