- Писать функции с типами параметров и возвращаемого значения и объяснять роль
strict_types - Использовать аргументы по умолчанию, именованные аргументы и переменное число аргументов
- Применять
array_map,array_filter,array_reduceиusortсо стрелочными функциями и замыканиями
Представь, что на сайте магазина цена товара с НДС считается в десяти разных местах. Когда ставка налога изменится, придётся исправлять десять мест — и одно обязательно забудется. Эту проблему решает функция: ты пишешь код один раз, даёшь ему имя и вызываешь где угодно.
Типизированные функции
Функция объявляется ключевым словом function. В современном PHP принято указывать типы параметров (float $price) и тип возвращаемого значения (: float). Функция, которая ничего не возвращает, помечается : void, функция, которая может вернуть и null, — ?string, а параметр, принимающий один из нескольких типов, записывается как int|float.
<?php
declare(strict_types=1);
function fullPrice(float $price, int $quantity = 1): float
{
return $price * $quantity;
}
function greet(string $name): string
{
return "Hello, $name!";
}
echo greet("Aysel"), "\n";
echo fullPrice(2.5, 4), "\n";
echo fullPrice(7.5), "\n";Hello, Aysel! 10 7.5
declare(strict_types=1); в первой строке файла включает строгий режим. В нём PHP не позволяет передать строку "5" в параметр типа int и выбрасывает TypeError. Без строгого режима PHP пытается преобразовать значение, и ошибки остаются незамеченными. Единственное исключение: int всегда можно передать в параметр типа float.
function add($a, $b)
{
return $a + $b;
}
echo add("5", "3"); // 8, works by accidentdeclare(strict_types=1);
function add(int $a, int $b): int
{
return $a + $b;
}
echo add("5", "3"); // TypeErrorАргументы по умолчанию, именованные и переменные
Если у параметра есть значение по умолчанию, его можно не указывать при вызове. Начиная с PHP 8 есть именованные аргументы: написав bold: true, ты пропускаешь промежуточные параметры и передаёшь нужный по имени. ...$numbers собирает любое число аргументов в массив, а при вызове ...$marks «распаковывает» массив в отдельные аргументы.
<?php
function makeTag(string $text, string $tag = "p", bool $bold = false): string
{
$inner = $bold ? "<b>$text</b>" : $text;
return "<$tag>$inner</$tag>";
}
function average(float ...$numbers): float
{
return array_sum($numbers) / count($numbers);
}
echo makeTag("Hello"), "\n";
echo makeTag("Title", "h1"), "\n";
echo makeTag("Warning", bold: true), "\n";
echo average(4, 5, 3), "\n";
$marks = [5, 5, 4, 4];
echo average(...$marks), "\n";<p>Hello</p> <h1>Title</h1> <p><b>Warning</b></p> 4 4.5
Анонимные функции и замыкания
В PHP функция — это значение: безымянную функцию можно записать в переменную и вызвать позже. Чтобы видеть внешнюю переменную, анонимная функция «захватывает» её через use ($rate) — такую функцию называют замыканием (closure). Стрелочная функция fn($x) => ... (PHP 7.4) короче: она состоит из одного выражения и захватывает внешние переменные автоматически.
<?php
$rate = 1.7;
$toAzn = function (float $usd) use ($rate): float {
return $usd * $rate;
};
$toUsd = fn(float $azn): float => round($azn / $rate, 2);
echo $toAzn(10), "\n";
echo $toUsd(34), "\n";
function makeCounter(): Closure
{
$count = 0;
return function () use (&$count): int {
return ++$count;
};
}
$next = makeCounter();
$next();
$next();
echo $next(), "\n";17 20 3
use ($rate) захватывает копию значения. А use (&$count) ссылается на саму переменную, поэтому счётчик растёт при каждом вызове и продолжает жить после завершения makeCounter. Стрелочные функции всегда захватывают по значению и не могут изменить внешнюю переменную.
Функции внутри функций для массивов
Чаще всего замыкания применяют с функциями для массивов. array_map преобразует каждый элемент, array_filter оставляет элементы, прошедшие проверку, array_reduce «сворачивает» массив в одно значение, а usort сортирует с помощью твоей функции сравнения. Ниже мы добавляем к ценам НДС 18 % и расставляем учеников по баллам.
<?php
$prices = [12, 45, 7, 30];
$withVat = array_map(fn($p) => $p * 1.18, $prices);
echo implode(", ", $withVat), "\n";
$expensive = array_filter($prices, fn($p) => $p > 10);
print_r($expensive);
$total = array_reduce($prices, fn($sum, $p) => $sum + $p, 0);
echo $total, "\n";
$students = [
["name" => "Murad", "score" => 78],
["name" => "Leyla", "score" => 95],
["name" => "Elvin", "score" => 86],
];
usort($students, fn($a, $b) => $b["score"] <=> $a["score"]);
echo implode(", ", array_column($students, "name")), "\n";14.16, 53.1, 8.26, 35.4
Array
(
[0] => 12
[1] => 45
[3] => 30
)
94
Leyla, Elvin, MuradГлавное
- Указывай типы параметров и возвращаемого значения;
declare(strict_types=1)запрещает автоматические преобразования и выявляет ошибки. - Параметры со значением по умолчанию можно опускать, а именованные аргументы (
bold: true) позволяют пропускать промежуточные. ...$argsсобирает аргументы в массив, а...$arrayпри вызове распаковывает массив в аргументы.- Замыкание захватывает внешние переменные через
use(по ссылке — с&), а стрелочная функцияfn— автоматически и по значению. array_map,array_filter,array_reduceиusortс замыканиями обрабатывают массивы коротко и понятно;array_filterсохраняет ключи.
Проверь себя
Вопросов: 10. Каждый правильный ответ приносит XP.
declare(strict_types=1);. Что произойдёт, если вызвать function add(int $a, int $b): int как add("5", "3")?