Глиф Учебники

Урок 5. Функции

Курс «PHP» · урок 5 из 10 · 4 минуты чтения

Функция — именованный кусок кода, который можно вызвать сколько угодно раз. Если одно и то же действие встречается в программе дважды, его пора вынести в функцию: так код короче, а исправлять ошибку придётся в одном месте, а не в десяти.

Своя функция

PHP
<?php
function greet(string $name): string
{
    return "Привет, $name!";
}

echo greet("Анна") . "\n";
echo greet("Олег") . "\n";
Вывод
Привет, Анна!
Привет, Олег!

Из чего состоит объявление:

function greet(string $name): string { return "Привет, $name!"; } имя функции параметр и его тип тип результата и return вызов greet("Анна") в $name "Анна" return "Привет, $name!" результат "Привет, Анна!"
В объявлении greet видны имя, параметр $name с типом string и тип результата; при вызове greet("Анна") строка "Анна" попадает в $name, а return отдаёт "Привет, Анна!".

Функция, которая ничего не возвращает, а, например, только выводит текст, получает тип void. Имена функций, в отличие от переменных, не зависят от регистра, но вызывать функцию принято так, как она объявлена. Объявить две функции с одним именем нельзя — будет ошибка Cannot redeclare.

Значения по умолчанию и именованные аргументы

PHP
<?php
function power(int $base, int $exp = 2): int
{
    return $base ** $exp;
}

echo power(5) . "\n";
echo power(2, 10) . "\n";
echo power(exp: 3, base: 4) . "\n";
Вывод
25
1024
64

У параметра $exp есть значение по умолчанию, поэтому при вызове его можно не указывать. Параметры со значением по умолчанию ставят в конец списка. С PHP 8.0 аргументы можно передавать по имени — exp: 3 — в любом порядке. Это удобно, когда параметров много: вызов power(exp: 3, base: 4) читается без заглядывания в объявление.

function power(int $base, int $exp = 2): int вызов $base $exp результат power(5) 5 2 25 power(2, 10) 2 10 1024 power(exp: 3, base: 4) 4 3 64 значение по умолчанию exp: 3, base: 4 — по имени, в любом порядке
power(5) берёт для $exp значение по умолчанию 2 и даёт 25, power(2, 10) даёт 1024, а в power(exp: 3, base: 4) аргументы попадают в параметры по именам — результат 64.

Типы и strict_types

Типы параметров — подсказка и защита: передать в функцию неподходящее значение не получится. Чаще всего встречаются int, float, string, bool, array, а также:

По умолчанию PHP мягко приводит типы: строку "21" в параметр int он превратит в число 21. Строгий режим включается первой строкой файла:

PHP
<?php
declare(strict_types=1);

function twice(int $n): int
{
    return $n * 2;
}

echo twice(21) . "\n";
echo twice("21") . "\n";

Первый вызов выведет 42, а второй остановит программу ошибкой TypeError с текстом Argument #1 ($n) must be of type int, string given. Без строки declare второй вызов тоже вывел бы 42. Строгий режим ловит ошибки раньше, поэтому его включают во многих проектах. Действует он на вызовы в том файле, где объявлен.

Область видимости

Переменные внутри функции свои. Переменные снаружи функция не видит:

PHP
<?php
$site = "glif.by";

function showSite(): void
{
    echo $site;
}

showSite();

Вместо адреса PHP выведет предупреждение Undefined variable $site. Правильный способ — передать значение параметром: function showSite(string $site) и вызов showSite($site). Существует и слово global, которое открывает функции внешнюю переменную, но так код быстро запутывается: непонятно, кто и где её меняет.

Без параметра "glif.by" $site showSite(); внутри функции echo $site; Undefined variable $site Через параметр "glif.by" $site showSite($site); function showSite(string $site) "glif.by" $site вывод: glif.by
Внутри функции не видна переменная $site, созданная снаружи, — echo $site даёт Undefined variable; переданная параметром, та же строка "glif.by" внутри функции доступна.

Несколько результатов

Функция возвращает одно значение, но им может быть массив. Его удобно сразу разложить по переменным:

PHP
<?php
function minMax(array $numbers): array
{
    return [min($numbers), max($numbers)];
}

[$low, $high] = minMax([3, 9, 1, 7]);
echo "От $low до $high\n";
Вывод
От 1 до 9

Стрелочные и анонимные функции

Функцию можно создать без имени и передать другой функции. Короче всего — стрелочная функция fn:

PHP
<?php
$numbers = [1, 2, 3, 4, 5, 6];
$squares = array_map(fn($n) => $n * $n, $numbers);
$even = array_filter($numbers, fn($n) => $n % 2 === 0);
echo implode(" ", $squares) . "\n";
echo implode(" ", $even) . "\n";
Вывод
1 4 9 16 25 36
2 4 6

array_map применяет функцию к каждому элементу и собирает новый массив, array_filter оставляет элементы, для которых функция вернула true. Стрелочная функция состоит из одного выражения и видит переменные снаружи.

Сортировка по своему правилу — usort. Правило сравнивает два элемента; оператор <=> («космический корабль») возвращает -1, 0 или 1:

PHP
<?php
$users = [
    ["name" => "Олег", "age" => 34],
    ["name" => "Анна", "age" => 19],
    ["name" => "Ира", "age" => 27],
];
usort($users, fn($a, $b) => $a["age"] <=> $b["age"]);
foreach ($users as $user) {
    echo "{$user['name']} ({$user['age']})\n";
}
Вывод
Анна (19)
Ира (27)
Олег (34)

Если в функции несколько строк, пишут анонимную функцию function. Внешние переменные ей передают явно через use:

PHP
<?php
$discount = 10;
$apply = function (int $price) use ($discount): int {
    $result = $price - $discount;
    return max($result, 0);
};
echo $apply(25) . "\n";
echo $apply(5) . "\n";
Вывод
15
0

Встроенные функции

В PHP тысячи готовых функций: для строк, массивов, дат, файлов, математики. Прежде чем писать свою, поищите готовую: наберите имя функции или задачу в поиске на php.net. У каждой функции там описаны параметры, возвращаемое значение и примеры.

Частые ошибки

Коротко

Проверьте себя

1. Что выведет программа?
PHP
<?php
function add(int $a, int $b = 10): int
{
    return $a + $b;
}
echo add(5);
2. Функция обращается к переменной $total, созданной вне функции. Что произойдёт?
3. Что делает declare(strict_types=1);?
4. Что вернёт array_filter([1, 2, 3, 4], fn($n) => $n > 2)?