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

Функция принимает данные и возвращает результат

<?php
declare(strict_types=1);

function formatBookLabel(string $title, int $year): string
{
    return $title . ' — ' . $year;
}

$label = formatBookLabel('Дюна', 1965);
echo $label;

Параметры описаны типами, а : string фиксирует результат. Функция не печатает текст сама, а возвращает его. Это проще переиспользовать: вызывающий код решает, показать подпись, сохранить её или проверить.

Разделяйте вычисление и побочный эффект

Чистая функция получает аргументы и вычисляет результат. Запись в файл, вывод HTML или отправка письма — побочные эффекты: они меняют состояние за пределами функции. На старте полезно отделять одно от другого:

function isValidRating(int $rating): bool
{
    return $rating >= 1 && $rating <= 5;
}

if (isValidRating(5)) {
    echo 'Оценка подходит';
}

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

Не превращайте параметры по умолчанию в скрытое правило

Необязательный параметр полезен, если у него есть понятное стандартное значение:

function formatBookLabel(string $title, ?int $year = null): string
{
    if ($year === null) {
        return $title;
    }

    return $title . ' — ' . $year;
}

echo formatBookLabel('Дюна');
echo formatBookLabel('Дюна', 1965);

С PHP 8 можно передавать именованные аргументы, если у функции много параметров:

formatBookLabel(title: 'Дюна', year: 1965);

Имя аргумента должно совпадать с параметром. Изменение имени параметра может затронуть вызывающий код с именованными аргументами, поэтому публичные функции не переименовывают легкомысленно.

Один источник правил для оценок

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

function validateRating(int $rating): int
{
    if ($rating < 1 || $rating > 5) {
        throw new InvalidArgumentException('Оценка должна быть от 1 до 5.');
    }

    return $rating;
}

Здесь появляется исключение — способ сообщить о ситуации, когда функция не может выполнить обещание. Подробно разберём его позже. Сейчас важно, что правило проверки находится в одном месте.

Когда функция стала слишком большой

Если название приходится описывать целым предложением, например loadBooksAndFilterByStatusAndPrintHtml(), функция, вероятно, делает слишком много. Разделите чтение данных, отбор и отображение. У каждой функции должно быть одно понятное назначение, а типы параметров и результата должны это назначение прояснять.

В следующей части проект разрастётся на несколько файлов. Подключать их вручную через длинную цепочку require неудобно, поэтому познакомимся с Composer, пространствами имён и автозагрузкой.

Часть 5 из 16.

← Часть 4: Массивы PHP: собираем и фильтруем каталог книг · Часть 6: Composer и пространства имён PHP: подключаем классы →

Документация