Function arguments

Оновлено: 11.05.2023

Інформація може бути передана функціям через список аргументів, який є списком виразів, розділених комами. Аргументи обчислюються зліва направо перед викликом функції (випереджувальне обчислення).

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', // This trailing comma was not permitted before 8.0.0.
)
{
    // ...
}
?>

За замовчуванням, аргументи функції передаються за значенням (тобто, якщо значення аргументу всередині функції змінюється, воно не змінюється за межами функції). Щоб функція могла змінювати свої аргументи, їх потрібно передавати за посиланням.

Щоб аргумент у функцію завжди передавався за посиланням, додайте амперсанд (&) до імені аргументу у визначенні функції:

Приклад #3 Передача параметрів функції за посиланням

<?php
function add_some_extra(&$string)
{
    $string .= 'and something extra.';
}
$str = 'This is a string, ';
add_some_extra($str);
echo $str;    // outputs 'This is a string, and something extra.'
?>

Помилкою є передача в якості аргументу значення, яке повинно передаватись за посиланням.

Функція може визначати значення за замовчуванням для аргументів, використовуючи синтаксис, подібний до присвоювання змінної. Значення за замовчуванням використовується лише тоді, коли параметр не вказано; зокрема, зверніть увагу, що передача null не призводить до присвоєння значення за замовчуванням.

Приклад #4 Використання параметрів за замовчуванням у функціях

<?php
function makecoffee($type = "cappuccino")
{
    return "Making a cup of $type.\n";
}
echo makecoffee();
echo makecoffee(null);
echo makecoffee("espresso");
?>

Значеннями параметрів за замовчуванням можуть бути скалярні значення, масиви, спеціальний тип null і, починаючи з PHP 8.1.0, об'єкти, що використовують синтаксис new ClassName().

Приклад #5 Використання нескалярних типів як значень за замовчуванням

<?php
function makecoffee($types = array("cappuccino"), $coffeeMaker = NULL)
{
    $device = is_null($coffeeMaker) ? "hands" : $coffeeMaker;
    return "Making a cup of ".join(", ", $types)." with $device.\n";
}
echo makecoffee();
echo makecoffee(array("cappuccino", "lavazza"), "teapot");?>

Приклад #6 Використання об'єктів як значень за замовчуванням (починаючи з PHP 8.1.0)

<?php
class DefaultCoffeeMaker {
    public function brew() {
        return 'Making coffee.';
    }
}
class FancyCoffeeMaker {
    public function brew() {
        return 'Crafting a beautiful coffee just for you.';
    }
}
function makecoffee($coffeeMaker = new DefaultCoffeeMaker)
{
    return $coffeeMaker->brew();
}
echo makecoffee();
echo makecoffee(new FancyCoffeeMaker);
?>

Значення за замовчуванням має бути константним виразом, а не (наприклад) змінною, членом класу або викликом функції.

Зверніть увагу, що необов'язкові аргументи слід вказувати після обов'язкових, інакше їх не можна буде пропустити у викликах. Розглянемо наступний приклад:

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

<?php
function makeyogurt($container = "bowl", $flavour)
{
    return "Making a $container of $flavour yogurt.\n";
}
 
echo makeyogurt("raspberry"); // "raspberry" is $container, not $flavour
?>

А тепер порівняйте вищесказане з цим:

Приклад #8 Правильне використання аргументів функції за замовчуванням

<?php
function makeyogurt($flavour, $container = "bowl")
{
    return "Making a $container of $flavour yogurt.\n";
}
 
echo makeyogurt("raspberry"); // "raspberry" is $flavour
?>

Починаючи з версії PHP 8.0.0, іменовані аргументи можна використовувати для пропуску декількох необов'язкових параметрів.

Приклад #9 Правильне використання аргументів функції за замовчуванням

<?php
function makeyogurt($container = "bowl", $flavour = "raspberry", $style = "Greek")
{
    return "Making a $container of $flavour $style yogurt.\n";
}

echo makeyogurt(style: "natural");
?>

Починаючи з версії PHP 8.0.0, оголошення обов'язкових аргументів після необов'язкових є застарілим. Зазвичай це можна вирішити, опустивши значення за замовчуванням, оскільки воно ніколи не буде використано. Винятком з цього правила є аргументи виду Type $param = null, де нульове значення за замовчуванням робить тип неявно нульовим. Таке використання залишається дозволеним, хоча рекомендується використовувати явний тип, який можна обнулити.

Приклад #10 Оголошення необов'язкових аргументів після обов'язкових

<?php
 function foo($a = [], $b) {} // Default not used; deprecated as of PHP 8.0.0
 function foo($a, $b) {}      // Functionally equivalent, no deprecation notice

 function bar(A $a = null, $b) {} // Still allowed; $a is required but nullable
 function bar(?A $a, $b) {}       // Recommended
 ?>

Зауваження: Починаючи з версії PHP 7.1.0, пропуск параметра, який не має значення за замовчуванням, призводить до помилки ArgumentCountError; у попередніх версіях це призводило до появи попередження.

Примітка: Аргументи, що передаються за посиланням, можуть мати значення за замовчуванням.

PHP підтримує списки аргументів змінної довжини у визначених користувачем функціях за допомогою лексеми ....

Зауваження: Також можна отримати аргументи змінної довжини за допомогою функцій func_num_args(), func_get_arg() і func_get_args(). Цей спосіб не рекомендується, оскільки він використовувався до введення лексеми ....

Списки аргументів можуть містити лексему ... для позначення того, що функція приймає змінну кількість аргументів. Аргументи будуть передані у задану змінну у вигляді масиву:

Приклад #11 Використання ... для доступу до аргументів змінних

<?php
function sum(...$numbers) {
    $acc = 0;
    foreach ($numbers as $n) {
        $acc += $n;
    }
    return $acc;
}

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

... також можна використовувати під час виклику функцій для розпакування масиву, змінної або літералу, що проглядається, у список аргументів:

Приклад #12 Використання ... для надання аргументів

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

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

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

Ви можете вказати звичайні позиційні аргументи перед лексемою .... У цьому випадку до масиву, згенерованого ...., буде додано лише ті аргументи, які не збігаються з позиційним аргументом.

Також можна додати оголошення типу перед лексемою .... Якщо воно присутнє, то всі аргументи, перехоплені ..., повинні відповідати цьому типу параметра.

Приклад #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';

// This will fail, since null isn't a DateInterval object.
echo total_intervals('d', null);
?>

Нарешті, змінні аргументи також можна передавати за посиланням, додаючи до ... амперсанд (&).

Не потрібно спеціального синтаксису, щоб зазначити, що функція є варіаційною; однак доступ до аргументів функції має здійснюватися за допомогою функцій func_num_args(), func_get_args() та func_get_args().

Перший приклад вище був би реалізований наступним чином у старих версіях PHP:

Приклад #14 Доступ до аргументів-змінних у старих версіях PHP

<?php
function sum() {
    $acc = 0;
    foreach (func_get_args() as $n) {
        $acc += $n;
    }
    return $acc;
}

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

У PHP 8.0.0 введено іменовані аргументи як розширення існуючих позиційних параметрів. Іменовані аргументи дозволяють передавати аргументи у функцію на основі імені параметра, а не його позиції. Це робить значення аргументу самодокументованим, робить аргументи незалежними від порядку і дозволяє довільно пропускати значення за замовчуванням.

Іменовані аргументи передаються шляхом додавання до значення імені параметра, за яким слідує двокрапка. Допускається використання зарезервованих ключових слів як імен параметрів. Ім'я параметра повинно бути ідентифікатором, динамічне визначення не допускається.

Приклад #15 Синтаксис іменованих аргументів

<?php
myFunction(paramName: $value);
array_foobar(array: $value);

// NOT supported.
function_name($variableStoringParamName: $value);
?>

Приклад #16 Позиційні аргументи проти іменованих аргументів

<?php
// Using positional arguments:
array_fill(0, 100, 50);

// Using named arguments:
array_fill(start_index: 0, count: 100, value: 50);
?>

Порядок передачі іменованих аргументів не має значення.

Приклад #17 Той самий приклад, що й вище, але з іншим порядком параметрів

<?php
array_fill(value: 50, count: 100, start_index: 0);
?>

Іменовані аргументи можна комбінувати з позиційними. У цьому випадку іменовані аргументи повинні йти після позиційних. Також можна вказати лише деякі з необов'язкових аргументів функції, незалежно від їх порядку.

Приклад #18 Поєднання іменованих аргументів з позиційними

<?php
htmlspecialchars($string, double_encode: false);
// Same as
htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8', false);
?>

Багаторазова передача одного і того ж параметра призводить до виключення Error.

Приклад #19 Виникнення помилки при багаторазовій передачі одного і того ж параметру

<?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, можна використовувати іменовані аргументи після розпакування аргументів. Іменований аргумент не повинен перевизначати вже розпаковані аргументи.

Приклад #20 Використання іменованих аргументів після розпакування

<?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
?>