php Функции

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

function имя_функции([параметр [, ...]]) {
    // Инструкции
}

Определение функции начинается с ключевого слова function, за которым следует имя функции. Имя функции должно начинаться с алфавитного символа или подчеркивания, за которыми может следовать любое количество алфавитно-цифровых символов или символов подчеркивания.
После имени функции в скобках идет перечисление параметров. Даже если параметров у функции нет, то просто идут пустые скобки. Затем в фигурных скобках идет тело функции, содержащее набор инструкций.
Определим простейшую функцию:

<?php
function hello() {
    echo "Hello PHP";
}
?>

Данная функция называется hello. Она не имеет параметров, поэтому после названия функции идут пустые скобки. Блок функции содержит только одну инструкцию, которая выводит сообщение "Hello PHP".
Чтобы функция сработала, ее надо вызвать. Для вызова функции указывается ее имя, после которого в скобках идут значения для ее параметров (если, кончено, она имеет параметры):

название_функции (значения_для_параметров_функции);

Например, вызовем вышеопределенную функцию hello:

<?php
function hello() {
    echo "Hello PHP";
}
hello();    // вызов функции
?>

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

<?php
function hello() {
    echo "<h2>Hello PHP</h2>";
}
hello();
hello();
hello();
?>

Стоит отметить, что в данном случае сначала определяется функция, а затем она вызывается. Но мы также можем сделать наоборот:

<?php
hello();    // вызов функции
function hello() {
    echo "Hello PHP";
}
?>

Тем не менее есть исключения. В частности, при определении функции при определенном условии.

// hello();     // здесь будет ошибка
if(true) { 
    function hello() {
        echo "Hello PHP";
    }
    hello();
}

Параметры функции

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

<?php
function hello($name) {
    echo "Hello $name";
}
hello("Tom");
hello("Bob");
hello("Sam");
?>

Здесь функция hello определяет один параметр - $name. При наименовании параметров применяются те же правила, что и для переменных. Также название параметров начинается со знака доллара $. Единственное, что не нужно указывать значение для параметра.

function hello($name)

Внутри самой функции мы можем использовать параметр так же как обычные переменные. Например, в данном случае его значение выводится на веб-страницу:

echo "Hello $name";

В дальнейшем при вызове функции нам надо передать для параметра некоторое значение. Значения при вызове функции передаются в скобках, сколько функция определяет параметров, столько необходимо передать значений.
Так, в данном случае функция определяет один параметр, соответственно при вызове функции передается только одно значение. Однако при каждом вызове это может быть разное значение:

hello("Tom");
hello("Bob");
hello("Sam");

Если мы не передадим значение для параметра: hello();, то мы столкнемся с ошибкой.
В качестве значения в функцию может передаваться и значение переменной:

$userName = "Tom";
hello($userName);

Подобным образом можно определять функции и с большим количеством параметров:

<?php
function displayInfo($name, $age) {
    echo "<div>Имя: $name <br>Возраст: $age</div><hr>";
}
displayInfo("Tom", 36);
displayInfo("Bob", 39);
displayInfo("Sam", 28);
?>

Здесь функция displayInfo определяет два параметра, соответственно при вызове функции нам надо передать в функцию два значения. Значения отделяются запятой и передаются параметрам по позиции. Так, первое значение передается первому параметру, второе значение передается второму параметру и так далее.

Необязательные параметры

Выше при определении функции мы были обязаны передать для всех параметров функции значения. Например, если функция определяет два параметра, соответственно нам надо передать в ее вызов два значения. Однако, PHP позволяет сделать параметры необязательными. Такие параметры имеют значение по умолчанию, которое применяется, если при вызове функции не передано никакого значения.

<?php
function displayInfo($name, $age = 18) {
    echo "<div>Имя: $name <br>Возраст: $age</div><hr>";
}
displayInfo("Tom", 36);
displayInfo("Sam");
?>

Здесь параметр $age определяется как необязательный. Для этого ему присваивается начальное значение - число 18. Причем если функция содержит обязательные и необязательные параметры, то необязательные параметры должны определяться в конце (как в данном случае параметр $age).
При первом вызове в функцию передаются два значения: displayInfo("Tom", 36), поэтому параметр $age получит второе значение - число 36.
Во втором вызове в функцию передается одно значение: displayInfo("Sam"), поэтому параметр $age будет использовать значение по умолчанию - число 18.
Имя: Tom
Возраст: 36

Имя: Sam
Возраст: 18

Именнованные параметры

Начиная с версии 8.0 в PHP была добавлена поддержка именнованных параметров. Так, до PHP 8.0 при вызове функции значения можно было передать параметрам только по позиции. Именнованные параметры позволяют передавать значения параметрам по имени:

<?php
function displayInfo($name, $age = 18) {
    echo "<div>Имя: $name <br>Возраст: $age</div><hr>";
}
displayInfo(age: 23, name: "Bob");
displayInfo(name: "Tom", age: 36);
displayInfo(name: "Alice");
?>

При вызове функции сначала указывается название параметра (без символа $) и через двоеточие указывается значение параметра : age: 23, name: "Bob". И в этом случае нам необязательно соблюдать позицию параметров.

Можно сочетать передачу значений параметрам по имени и по позиции. При этом любые именованные необязательные параметры должны располагаться после НЕименованных параметров:

displayInfo("Tom", age: 36);

Переменное количество параметров

В PHP функция может принимать переменное количество параметров. Для этого у функции определяется один параметр, перед которым указывается оператор ... (три точки). Такой параметр рассматривается как массив:

<?php
function sum(...$numbers) {
    $result = 0;
    foreach($numbers as $number) {
        $result += $number;
    }
    echo "<p>Сумма: $result </p>";
}
sum(1, 2, 3);
sum(2, 3);
sum(4, 5, 8, 10);
?>

При обращении к подобной функции мы можем передавать в нее различное количество значений. Результат:
Сумма: 6

Сумма: 5

Сумма: 27
Но, допустим, готовый массив значений, которые мы хотим передать в функцию. Чтобы его передать в функцию, опять же применяется оператор ..., который указывается перед переменной массива:

<?php
function sum(...$numbers) {
    $result = 0;
    foreach($numbers as $number) {
        $result += $number;
    }
    echo "<p>Сумма: $result </p>";
}
$numbers = [3, 5, 7, 8];
sum(...$numbers);           // 23
?>

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

function getAverageScore($name, ...$scores) {
    $result = 0.0;
    foreach($scores as $score) {
        $result += $score;
    }
    $result = $result / count($scores);
    echo "<p> $name: $result </p>";
}
getAverageScore("Tom", 5, 5, 4, 5);
getAverageScore("Bob", 4, 3, 4, 4, 4);

Баллы успеваемости передаются через параметр $scores, который указывается в конце списка параметров. В самой функции для вычисления среднего балла все баллы складываются и делятся на их количество. Количество элементов массива можно подсчитать с помощью встроенной в PHP функции count(), в которую передается массив.

Возвращение значений и оператор return

Функция может возвращать некоторое значение - число, строку и т.д., то есть некоторый результат. Для возвращения значения в функции применяется оператор return, после которого указывается возвращаемое значение.
Например, получим из функции сумму двух чисел:

<?php
function add($a, $b) {
    return $a + $b;
}
$result = add(5, 6);
echo $result;           // 11
?>

Функция add() принимает два параметра и возвращает сумму их значений.
return $a + $b;
Поскольку функция возвращает значение, мы его можем присвоить переменной:
$result = add(5, 6);
Либо использовать напрямую:
echo add(4, 8);
Если после инструкции return в функции идут другие инструкции, то они не будут выполняться:

function add($a, $b) {
    $sum = $a + $b;
    return $sum;        // завершение функции
    echo "sum = $sum";  // эта строка не будет выполняться
}

В реальности даже если функция не использует оператор return, она все равно возвращает значение, только в этом случае это значение - null:

<?php
function add($a, $b) {
    $sum = $a + $b;
    echo "sum = $sum <br>";
}
$result = add(5, 6);
if($result === null)
    echo "result равен null";
else
    echo "result не равен null";
?>

Анонимные функции

Анонимные функции позволяют передавать в качестве параметров функции другие функции или присваивать их переменным.
Анонимная функция определяется как обычная функция за тем исключением, что она не имеет имени. Например:

$hello = function($name) {
    echo "Hello $name";
};

Здесь переменной $hello присваивается анонимная функция. Эта функция также определяется с помощью ключевого слова function. Она также принимает параметры - в данном случае параметр $name. И также она имеет некоторый блок операторов.
Для вызова подобной функции применяется имя представляющей ее переменной:
$hello("Tom");
Фактически подобная переменная применяется как стандартная функция.
Полный код:

<?php
$hello = function($name) {
    echo "Hello $name";
};
$hello("Tom");
$hello("Bob");
?>

Также анонимные функции могут возвращать некоторое значение:

<?php
$sum = function($a, $b) {
    return $a + $b;
};
$number = $sum(5, 11);  //16
echo $number;
?>

Распространенным случаем применения анонимных функций является передача их параметрам других функции. Таким анонимные функции еще называют функциями обратного вызова или коллбеками (callback function). Рассмотрим простейший пример:

<?php
function welcome($message) {
    $message();
}
welcome(function() {
    echo "Hello!";
});
?>

В данном случае функция welcome() имеет параметр $message, который внутри функции вызывается подобно функции $message().
При вызове функции welcome() параметру $message передается анонимная функция, которая выводит строку "Hello!". В этоге при вызове
$message();
Фактически будет выполняться функция

function() {
    echo "Hello!";
}

Подобным образом мы можем передавать одну функцию различные анонимные функции:

<?php
function welcome($message) {
    $message();
}
$goodMorning = function() {
echo "Доброе утро";
};
$goodEvening = function() {
echo "Добрый вечер";
};
welcome($goodMorning);          // Доброе утро
welcome($goodEvening);          // Добрый вечер
welcome(function() {
echo "Привет";
}); // Привет
?>

В чем польза подобной передачи анонимных функций в качестве параметров? А польза заключается в том, что мы можем определить функцию, но на момент определения функции точно не знать, какие действия она будет выполнять при вызове. Либо просто сделать логику функции более гибкой. Например, нам надо определить функцию которая выводит сумму элементов массива:

function sum($numbers) {
    $result = 0;
    foreach($numbers as $number) {
        $result += $number;
    }
    return $result;
}
$myNumbers = [-2, -1, 0, 1, 2, 3, 4, 5];
$numbersSum = sum($myNumbers);
echo $numbersSum;           // 12

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

<?php
function sum($numbers, $condition) {
    $result = 0;
    foreach($numbers as $number) {
        if($condition($number))
        {
            $result += $number;
        }
    }
    return $result;
}
// для четных чисел
$isEvenNumber = function($n){ return $n % 2 === 0;};
// для положительных чисел
$isPositiveNumber = function($n){ return $n > 0;};
$myNumbers = [-2, -1, 0, 1, 2, 3, 4, 5];
$positiveSum = sum($myNumbers, $isPositiveNumber);
$evenSum = sum($myNumbers, $isEvenNumber);
echo "Сумма положительных чисел: $positiveSum <br> Сумма четных чисел: $evenSum";
?>

Результат скрипта:
Сумма положительных чисел: 15
Сумма четных чисел: 4
Здесь функция sum() в качестве второго параметра - $condition принимает другую функцию. В цикле при переборе массива с помощью этой функции мы проверяем, удовлетворяет ли элемент массива условию:
if($condition($number))
Причем сейчас мы не знаем, что это будет за условие, как именно функция $condition будет работать. Мы только знаем, что она получает число и возвращает true, если число удовлетворяет условию, либо false - если не удовлетворяет.
И если только число соответствует условию, тогда прибавляем число к общему результату:
$result += $number;
При вызове функции sum() в качестве параметра $condition передаются конкретные анонимные функции. Например, функиция, которая определяет, является ли число четным:
$isEvenNumber = function($n){ return $n % 2 === 0;};
Логика функции проста: если остаток от деления числа на 2 равен 0, то число четное. и функция возвращает true.
Далее мы передаем эту функцию:
$evenSum = sum($myNumbers, $isEvenNumber);
В итоге при вызове if($condition($number)) фактически будет выполняться функция $isEvenNumber().

Замыкания / Closure

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

<?php
$number = 89;
$showNumber = function() {
    echo $number;
};
$showNumber();
?>

Анонимная функция, которая представлена переменной $showNumber, пытается обратиться к внешней переменной $number. Однако при выполнении скрипта мы увидим в браузере сообщение об ошибке:
Warning: Undefined variable $number in C:\localhost\hello.php on line 13
То есть по умолчанию переменной $number для анонимной функции не существует. Из данной ситуации мы можем выйти, использовав оператор global или массив $GLOBALS, которые рассматриваются в одной из последующих тем. Тем не менее замыкания также позволяют решить эту проблему. Так, трансформируем функцию в замыкание:

<?php
$number = 89;
$showNumber = function() use($number) {
    echo $number;
};
$showNumber();
?>

Выражение use() получает внешние переменные, которые анонимная функция собирается использовать. И теперь при ее выполении браузер выведет значение переменной $number.
Подобным образом функция-замыкание может захватывать и большее количество внешних переменных, а также как и другие функции применять параметры:

$a = 8;
$b = 10;
$closure = function($c) use($a, $b) {
    return $a + $b + $c;
};
$result = $closure(22); // 40
echo $result;

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

Стрелочные функции (arrow function) позволяют упростить запись анонимных функций, которые возвращают некоторое значение. И при этом стрелочные функции автоматически имеют доступ к переменным из внешнего окружения.
Стрелочная функция определяется с помощью оператора fn:

fn(параметры) => действия;

После оператора fn в скобках идет список параметров. Затем указывается оператор =>. А после него располагаются действия функции, которые возвращают некоторый результат.
Например:

$a = 8;
$b = 10;
$closure = fn($c) => $a + $b + $c;
$result = $closure(22); // 40

В данном случае определение стрелочной функции
$closure = fn($c) => $a + $b + $c;
Фактически будет аналогично:

$closure = function($c) use($a, $b) {
    return $a + $b + $c;
};

Только в отличие от стандартных анонимных функций стрелочный функции предоставляют более лаконичный синтаксис.
Также стрелочные функции могут применяться в качестве параметров функции:

function sum($numbers, $condition) {
    $result = 0;
    foreach($numbers as $number){
        if($condition($number))
        {
            $result += $number;
        }
    }
    return $result;
}
$myNumbers = [-2, -1, 0, 1, 2, 3, 4, 5];
$positiveSum = sum($myNumbers, fn($n)=>$n > 0);
$evenSum = sum($myNumbers, fn($n) => $n % 2 === 0);
echo "Сумма положительных чисел: $positiveSum <br> Сумма четных чисел: $evenSum";

Генераторы

Генератор предоставляет функцию, которая генерирует набор значений.
Для возвращения значения из функции применяется оператор yield. Но в отличие от return оператор yield сохраняет состояние функции, позволяя ей продолжать работу с того места, когда остановилось ее выполнение.
Например, определим простейшую функцию генератора:

function generator() {
    yield 21;
}

Здесь функция генератора фактически возвращает только одно число 21. Тем не менее мы можем перебирать результат функции генератора в цикле как стандартный массив:

foreach(generator() as $number) {
    echo $number; // 21
}

Подобным образом генератор может возвращать и большее количество значений:

function generateNumbers() {
    for ($i = 0; $i <= 5; $i++) {
        yield $i;
    }
}
foreach(generateNumbers() as $number) {
    echo $number; // 012345
}

В данном случае функция генератора generateNumbers() с помощью цикла генерирует значения от 0 до 5 включительно. Это все равно, если бы написали:

function generateNumbers() {
    yield 0;
    yield 1;
    yield 2;
    yield 3;
    yield 4;
    yield 5;
}

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

<?php
function generateNumbers() {
    for ($i = 10; $i <= 15; $i++) {
        yield $i;
    }
}
foreach(generateNumbers() as $index => $number)
{
    echo "$index - $number <br>"; // 012345
}
?>

Результат функции:
0 - 10
1 - 11
2 - 12
3 - 13
4 - 14
5 - 15

С помощью оператора from можно определять массив - источник данных для генератора:

function generateNumbers() {
    yield 1;
    yield from [2, 3, 4];
    yield 5;
}
foreach(generateNumbers() as $number)
{
    echo $number; // 12345
}

В данном случае функция generateNumbers() для генерации часть данных берет из массива [2, 3, 4] с помощью выражения yield from [2, 3, 4].
Функция генератора, как и любая функция может принимать параметры, что позволяет настраивать поведение генератора:

function generateNumbers($start, $end) {
    for($i = $start; $i < $end; $i++){
        yield $i;
    }
}
foreach(generateNumbers(4, 9) as $number)
{
    echo $number; // 45678
}

Но естественно может возникнуть вопрос: а зачем нужны генераторы? Разве мы не можем с тем же успехом перебирать обычный массив? Например:

$numbers = [1, 2, 3, 4, 5];
foreach($numbers as $number) {
    echo $number; // 12345
}

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

статья взята с сайта:

metanit.com

Обсуждение закрыто.