PHPDevs

Projekt obiektowy z Composerem i Twigiem? Czytaj!

Funkcje > Lekcja 3

Argumenty funkcji

Argumenty to dane, które chcemy przesłać do wnętrza naszej funkcji. Definiujemy je w momencie deklaracji funkcji, w nawiasach, oddzielając przecinkami. Przypisujemy im zmienne, których następnie możemy użyć wewnątrz funkcji. Z kolei przy wywołaniu funkcji musimy podać ich wartości.

<?php
function showNumbers($number1, $number2)
{
    echo $number1 . ' ' . $number2;
}
showNumbers(4, 3); // result: 4 3
showNumbers(23, 7); // result: 23 7

Teraz może zacząłeś zastanawiać się po co nam te argumenty i dobrze, to właściwe pytanie. Rzecz jest w tym, że zmienne zadeklarowane poza funkcją nie są w niej widoczne. Podobnie zmienne stworzone w funkcji - nie są widoczne poza nią. Jeśli więc chcemy przekazać coś do funkcji, musimy użyć argumentów.

Jeśli jeszcze coś jest niejasne to z pewnością zrozumiesz po obejrzeniu przykładu:

<?php
$number1 = 5;
function showNumbers()
{
    var_dump($number1); // result: Notice: Undefined variable: number1
    $number2 = 8;
}

showNumbers();
var_dump($number2); // result: Notice: Undefined variable: number2

Uwaga

Zmienne globalne, nazywane też globalami, umożliwiają inne obejście tego problemu. Jest to jednak bardzo zły sposób. Zagrożeń w związku ze zmiennymi globalnymi jest bardzo wiele - wystarczy, że inny programista nie zauważy ustawienia zmiennej jako globalnej i już może z dowolnego miejsca kodu nieświadomie zepsuć coś w innym.

<?php
$number1 = 5;
function showNumbers()
{
    global $number1, $number2;
    var_dump($number1); // result: int(5)
    $number2 = 8;
}

showNumbers();
var_dump($number2); // result: int(8)

Przykład pokazuję, abyś wiedział co to jest, gdy spotkasz taki zapis. Podkreślam jednak raz jeszcze, że stanowczo odradzam używanie globali i w kursie się z pewnością więcej nie pojawią.

Wracamy do naszego celu i kodu z poprzedniej lekcji. Poprawmy go tak, aby zmienne do działań można było przekazać z zewnątrz, przez argumenty.

<?php

$operation = '+';
$number1 = 8;
$number2 = 4;

function operationAddition($number1, $number2)
{
    echo $number1 + $number2;
}

function operationSubtraction($number1, $number2)
{
    echo $number1 - $number2;
}

function operationMultiplication($number1, $number2)
{
    echo $number1 * $number2;
}

function operationDivision($number1, $number2)
{
    echo $number1 / $number2;
}

switch ($operation) {
    case '+':
        operationAddition($number1, $number2);
        break;
    case '-':
        operationSubtraction($number1, $number2);
        break;
    case '*':
        operationMultiplication($number1, $number2);
        break;
    case '/':
        operationDivision($number1, $number2);
        break;
}

Dla jasności: zmienne, których wartości podstawiamy oraz zmienne tworzone wewnątrz funkcji jako argumenty, nie muszą nazywać się tak samo - w powyższym przykładzie to czysty przypadek.

Wartość domyślna

Przy wywołaniu funkcji musimy podać wartości dla wszystkich zadeklarowanych argumentów. Jeżeli tego nie zrobimy, zostanie zwrócony błąd. Istnieje jednak możliwość zdefiniowania wartości domyślnych dla każdego (lub tylko części) z nich - wtedy rzecz jasna błędów w przypadku nieprzekazania wartości nie będzie.

Domyślną wartość możesz skojarzyć z przypisywaniem wartości zmiennych, gdyż definiujemy ją tak jak przypisanie, przy użyciu =. Istnieje tylko jedna istotna uwaga: robimy to od końca (czyli od ostatniego, od prawej strony). Dlaczego? Ustawiamy od końca argumenty jako opcjonalne do wywołania funkcji, dzięki czemu w momencie ich podania interpreter wie, do których zmiennych je przekazać. Gdybyśmy mogli sobie ustawić taką wartość na przykład dla pierwszego argumentu, skąd interpreter miałby wiedzieć, który argument chcemy pominąć i użyć domyślnej wartości?

<?php
$number = 3;
function showNumbers($number1, $number2 = 1)
{
    echo $number1 . ' ' . $number2;
}
showNumbers($number); // result: 3 1
<?php
$number = 3;
function showNumbers($number1 = 1, $number2) // próbujemy powiedzieć, aby pierwszy argument miał wartość domyślną
{
    echo $number1 . ' ' . $number2;
}
showNumbers($number); // result: Fatal error: Too few arguments to function showNumbers()
// podaliśmy tylko pierwszy argument, a drugiego nie, pomimo tego, że jest obowiązkowy

Definiuj więc argumenty tak, aby te opcjonalne znajdowały się możliwie na końcu.

Typy argumentów

Od PHP 7 istnieje możliwość określenia typów argumentów, jakie mają zostać przesłane (dla ścisłości: wcześniej można było określać typ tylko jeśli przesyłany był obiekt, ale o tym gdzieś dalej). Robimy to poprzez dodanie typu przed nazwą zmiennej w deklaracji funkcji. Dla przykładu tak:

<?php
function showNumbers(int $number1, int $number2)
{
    echo $number1 . ' ' . $number2;
}
showNumbers(4, 3); // result: 4 3
showNumbers(23, 7); // result: 23 7

Co się stanie gdy podamy wartość innego typu, niż zadeklarowany? Pewnie spodziewasz się, że wyrzucony zostanie błąd, ale nie do końca tak jest. Zależy to od sytuacji. Gdy zadeklarujesz, że zmienna $number ma być typu int, a prześlesz tekst, to owszem, działanie kodu zakończy się błędem. Jednak gdy do zadeklarowanego inta spróbujesz przesłać na przykład wartość typu float to kod zadziała bez zarzutu - interpreter sam przekonwertuje liczbę zmiennoprzecinkową na całkowitą ("obetnie" końcówkę).

<?php
function showNumber(int $number)
{
    echo $number;
}
showNumber(5); // result: 5
showNumber(5.7); // result: 5
showNumber('PHPDevs'); // result: Uncaught TypeError: Argument 1 passed to showNumber() must be of the type integer, string given

Gdybyśmy jednak chcieli precyzyjnie określić, że zmienna ma być takiego typu jaki zadeklarowaliśmy, możemy to wymusić. Wystarczy (najlepiej na początku pliku) użyć declare i ustawić strict_types na 1.

<?php
declare(strict_types=1);
function showNumber(int $number)
{
    echo $number;
}
showNumber(5); // result: 5
showNumber(5.7); // result: Uncaught TypeError: Argument 1 passed to showNumber() must be of the type integer, float given
showNumber('PHPDevs'); // result: Uncaught TypeError: Argument 1 passed to showNumber() must be of the type integer, string given

Z nową wiedzą przeróbmy znów nasz kalkulator. Użycie wartości domyślnej raczej się nie sprawdzi, więc to tutaj odpuścimy (przećwiczysz w zadaniu domowym), ale już deklarację typu jak najbardziej możemy sobie dodać. Jako iż może zaistnieć potrzeba operowania na liczbach z przecinkiem, pozwólmy na wartości typu float.

<?php

function operationAddition(float $number1, float $number2) { /* ... */ }

function operationSubtraction(float $number1, float $number2) { /* ... */ }

function operationMultiplication(float $number1, float $number2) { /* ... */ }

function operationDivision(float $number1, float $number2) { /* ... */ }
    
// ...

Ćwiczenia

  1. Przygotuj funkcję showName wyświetlającą imię przekazane do niej jako argument.

    Przykładowe rozwiązanie

  2. Napisz funkcję prepareCart sprawdzającą, czy klient może złożyć zamówienie o cenie $price, gdy stan jego konta wynosi $money. Zadeklaruj odpowiednie typy dla argumentów. Trzeci argument $promotion powinien być typu logicznego (prawda lub fałsz). Wartością domyślną w przypadku jego nieprzekazania powinno być false. W przypadku gdy promocja ma obowiązywać (true) od łącznej ceny zamówienia ($price) należy odjąć 10. Jeśli klient może dokonać zamówienia wyświetl komunikat "OK".
    <?php
    $price = 22.90;
    $money = 50;
    // your code here
    

    Przykładowe rozwiązanie

Poprzednia lekcja Następna lekcja

Udostępnij

  • Facebook
  • Twitter
  • Google+

Komentarze