Аргументы функции

Функция принимает информацию в виде списка аргументов — выражений через запятую. Аргументы вычисляются слева направо перед действительным вызовом функции. Такое вычисление называют энергичным.

PHP поддерживает передачу аргументов по значению (по умолчанию), передачу аргументов по ссылке, и значения по умолчанию. Списки аргументов переменной длины и именованные аргументы также поддерживаются.

Пример #1 Передача массивов в функции

<?php

function takes_array($input)
{
echo
"$input[0] + $input[1] = ", $input[0]+$input[1];
}

?>

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

Пример #2 Список аргументов функции с конечной запятой

<?php

function takes_many_args(
$first_arg,
$second_arg,
$a_very_long_argument_name,
$arg_with_default = 5,
$again = 'a default string', // Конечная запятая не допускалась до PHP 8.0.0
) {
// ...
}

?>

Передача аргументов по ссылке

По умолчанию аргументы функции передаются по значению (поэтому если значение аргумента внутри функции изменится, значение не изменится за пределами функции). Аргументы передают по ссылке, чтобы разрешить функции изменять значения аргументов.

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

Пример #3 Передача аргументов по ссылке

<?php

function add_some_extra(&$string)
{
$string .= 'и кое-что ещё.';
}

$str = 'Это строка, ';
add_some_extra($str);
echo
$str; // Выведет «Это строка, и кое-что ещё.»

?>

Передача в виде аргумента значения в параметр, который ждёт ссылку, — ошибка.

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

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

Пример #4 Значения по умолчанию для параметров в функциях

<?php

function makecoffee($type = "капучино")
{
return
"Готовим чашку $type.\n";
}

echo
makecoffee();
echo
makecoffee(null);
echo
makecoffee("эспрессо");

?>

Результат выполнения приведённого примера:

 Готовим чашку капучино. Готовим чашку . Готовим чашку эспрессо. 

Значениями по умолчанию для параметров разрешается указывать скалярные значения, массивы (array), специальный тип null и начиная с PHP 8.1.0 объекты, которые создают синтаксисом new ClassName().

Пример #5 Нескалярные типы как значения по умолчанию

<?php

function makecoffee($types = array("капучино"), $coffeeMaker = NULL)
{
$device = is_null($coffeeMaker)
?
"вручную"
: $coffeeMaker
;

return
"Готовлю чашку " . join(", ", $types) . " $device. \n";
}

echo
makecoffee();
echo
makecoffee(array("капучино", "лавацца"), "в чайнике");

?>

Результат выполнения приведённого примера:

 Готовлю чашку капучино вручную. Готовлю чашку капучино, лавацца в чайнике. 

Пример #6 Объекты как значения по умолчанию, с PHP 8.1.0

<?php

class DefaultCoffeeMaker
{
public function
brew()
{
return
"Приготовление кофе.\n";
}
}

class
FancyCoffeeMaker
{
public function
brew()
{
return
"Приготовление прекрасного кофе только для вас.\n";
}
}

function
makecoffee($coffeeMaker = new DefaultCoffeeMaker)
{
return
$coffeeMaker->brew();
}

echo
makecoffee();
echo
makecoffee(new FancyCoffeeMaker);

?>

Результат выполнения приведённого примера:

 Приготовление кофе. Приготовление прекрасного кофе только для вас. 

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

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

Пример #7 Неправильное определение значений по умолчанию для параметров функции

<?php

function makeyogurt($container = "миску", $flavour)
{
return
"Делаем $container с $flavour йогуртом.\n";
}

echo
makeyogurt("малиновым"); // Значение «малиновым» получит параметр $container, а не $flavour

?>

Результат выполнения приведённого примера:

 Fatal error: Uncaught ArgumentCountError: Too few arguments to function makeyogurt(), 1 passed in example.php on line 42 

Теперь сравним приведённый пример со следующим примером:

Пример #8 Правильное определение значений по умолчанию для параметров функции

<?php

function makeyogurt($flavour, $container = "миску")
{
return
"Делаем $container с $flavour йогуртом.\n";
}

echo
makeyogurt("малиновым"); // Значение «малиновым» получит параметр $flavour

?>

Результат выполнения приведённого примера:

 Делаем миску с малиновым йогуртом. 

Начиная с PHP 8.0.0 для пропуска нескольких необязательных параметров передают именованные аргументы.

Пример #9 Правильное определение значений по умолчанию для параметров функции

<?php

function makeyogurt($container = "миску", $flavour = "малиновым", $style = "греческим")
{
return
"Делаем $container с $flavour$style йогуртом.\n";
}

echo
makeyogurt(style: "натуральным");

?>

Результат выполнения приведённого примера:

 Делаем миску с малиновым натуральным йогуртом. 

С PHP 8.0.0 объявление обязательных аргументов после необязательных устарело. Обычно из таких ситуаций выходят за счёт отказа от значения по умолчанию, поскольку функция никогда не присвоит параметру, в который передали аргумент, значение по умолчанию. Исключение из этого правила — аргументы вида Type $param = null, где null по умолчанию делает тип неявно обнуляемым. Такое определение остаётся допустимым, хотя рекомендуется указывать явный обнуляемый тип.

Пример #10 Объявление необязательных аргументов после обязательных аргументов

<?php

function foo($a = [], $b) {} // Функция не присвоит значение по умолчанию; устарело с PHP 8.0.0
function foo($a, $b) {} // Функционально эквивалентны, без уведомления об устаревании
function bar(A $a = null, $b) {} // Всё ещё разрешается; переменная $a обязательна, но допускает значение null
function bar(?A $a, $b) {} // Рекомендуется

?>

Замечание: Начиная с PHP 7.1.0 пропуск параметра, для которого не задали значение по умолчанию, выбрасывает исключение ArgumentCountError; в предыдущих версиях это выдавало предупреждение.

Замечание: Для параметров, которые ждут, что аргумент передадут по ссылке, разрешается устанавливать значения по умолчанию.

Списки аргументов переменной длины

PHP поддерживает в пользовательских функциях списки аргументов переменной длины, параметры для которых определяют оператором из трёх точек ..., который называется spread-оператором.

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

Пример #11 Оператор ... для доступа к аргументам

<?php

function sum(...$numbers) {
$acc = 0;

foreach (
$numbers as $n) {
$acc += $n;
}

return
$acc;
}

echo
sum(1, 2, 3, 4);

?>

Результат выполнения приведённого примера:

 10 

Spread-оператор ... указывают также при вызове функции, чтобы распаковать в список аргументов массив (array), или распаковать переменную или литерал, которые принадлежат типу Traversable:

Пример #12 Передача аргументов через spread-оператор ...

<?php

function add($a, $b) {
return
$a + $b;
}

echo
add(...[1, 2])."\n";

$a = [1, 2];
echo
add(...$a);

?>

Результат выполнения приведённого примера:

 3 3 

Разрешается указывать стандартные позиционные параметры, а за ними параметр с оператором ..., тогда оператор ... сгенерирует и добавит в массив только конечные аргументы, позиции которых не совпали с позиционными аргументами.

Разрешается также добавлять перед оператором ...объявление типа. Тогда аргументы, которые захватил оператор ..., должны соответствовать типу параметра.

Пример #13 Аргументы с подсказкой типа

<?php

function total_intervals($unit, DateInterval ...$intervals) {
$time = 0;

foreach (
$intervals as $interval) {
$time += $interval->$unit;
}

return
$time;
}

$a = new DateInterval('P1D');
$b = new DateInterval('P2D');

echo
total_intervals('d', $a, $b).' days';

// Это не сработает, поскольку null — не объект класса DateInterval
echo total_intervals('d', null);

?>

Результат выполнения приведённого примера:

 3 days Catchable fatal error: Argument 2 passed to total_intervals() must be an instance of DateInterval, null given, called in - on line 14 and defined in - on line 2 

В финале добавим, что разрешается также передавать аргументы переменной длины по ссылке, для этого перед оператором ... указывают амперсанд (&).

Именованные аргументы

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

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

Пример #14 Синтаксис именованного аргумента

<?php

myFunction
(paramName: $value);
array_foobar(array: $value);

// НЕ поддерживается
function_name($variableStoringParamName: $value);

?>

Пример #15 Позиционные аргументы по сравнению с именованными аргументами

<?php

// Передача позиционных аргументов:
array_fill(0, 100, 50);

// Передача именованных аргументов:
array_fill(start_index: 0, count: 100, value: 50);

?>

Порядок передачи именованных аргументов неважен.

Пример #16 Тот же пример, но с другим порядком аргументов

<?php

array_fill
(value: 50, count: 100, start_index: 0);

?>

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

Пример #17 Объединение именованных аргументов с позиционными аргументами

<?php

htmlspecialchars
($string, double_encode: false);

// То же самое
htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8', false);

?>

Передача одного и того же аргумента больше одного раза выбросит исключение Error.

Пример #18 Ошибка, которая возникает при передаче одного и того же параметра больше одного раза

<?php

function foo($param) {}

foo(param: 1, param: 2);
// Error: Named parameter $param overwrites previous argument

foo(1, param: 2);
// Error: Named parameter $param overwrites previous argument

?>

Начиная с PHP 8.1.0 разрешается передавать именованные аргументы после распаковки аргументов. Именованный аргумент не должен переопределять распакованный аргумент.

Пример #19 Пример передачи именованных аргументов после распаковки

<?php

function foo($a, $b, $c = 3, $d = 4) {
return
$a + $b + $c + $d;
}

var_dump(foo(...[1, 2], d: 40)); // 46
var_dump(foo(...['b' => 2, 'a' => 1], d: 40)); // 46
var_dump(foo(...[1, 2], b: 20)); // Fatal error: Named parameter $b overwrites previous argument

?>
To Top