PHP: Advanced Functions

You've got the function basics down. This lesson lets you write more flexible, more modern, more PHP 8–style functions — variadic parameters, named arguments, arrow functions — all fruits of PHP's continuous evolution.

1. Variadic Parameters (...$args)

Don't know how many arguments will be passed? Use ... to capture them all into an array:

PHP
<?php
function sum(...$numbers): int {
    return array_sum($numbers);
}

echo sum(1, 2);           // 3
echo sum(1, 2, 3, 4, 5);  // 15
echo sum();               // 0

// You can also have fixed parameters before the variadic ones
function sendMessage(string $to, string ...$messages): void {
    foreach ($messages as $msg) {
        echo "Sent to {$to}: {$msg}<br>";
    }
}

sendMessage("John", "Good morning", "How's lunch?", "Good night");
// Sent to John: Good morning
// Sent to John: How's lunch?
// Sent to John: Good night
?>

▶ Example: ... to Spread an Array into Arguments

Output:

TEXT 📖 Display only
6
PHP
<?php
function add(int $a, int $b, int $c): int {
    return $a + $b + $c;
}

$nums = [1, 2, 3];
echo add(...$nums);  // 6 (the array is spread into 3 separate arguments)

// Commonly used with array_push and similar functions
$stack = ["a", "b"];
array_push($stack, ...["c", "d", "e"]);
print_r($stack);  // ["a", "b", "c", "d", "e"]
?>

Output:

TEXT 📖 Display only
6
Array
(
    [0] => a
    [1] => b
    [2] => c
    [3] => d
    [4] => e
)

... works in both directions — in a function definition it packs arguments into an array; at a call site it spreads an array into arguments.


2. Named Arguments (PHP 8.0)

No need to memorize parameter order — pass arguments by name:

▶ Example: Named Arguments

Output:

TEXT 📖 Display only
(no visible output - function defined)
PHP
<?php
function createUser(
    string $name,
    int $age,
    string $email = "",
    bool $isAdmin = false
): array {
    return compact('name', 'age', 'email', 'isAdmin');
}

// Traditional: must follow parameter order
$u1 = createUser("John", 25, "john@example.com", true);

// Named arguments: order doesn't matter — skip parameters with defaults
$u2 = createUser(
    name: "Jane",
    age: 22,
    isAdmin: true
    // email uses the default
);

// When a function has many parameters, named arguments dramatically improve readability
setcookie(
    name: "theme",
    value: "dark",
    expires_or_options: time() + 3600,
    httponly: true
);
?>

Output:

TEXT 📖 Display only
Array
(
    [name] => Jane
    [age] => 22
    [email] => 
    [isAdmin] => 1
)
💡 Tip: Named arguments are especially useful when: (1) a function has many parameters, most with defaults; (2) you only want to pass the last few arguments; (3) you want self-documenting code — createUser(name: "John", age: 25) is instantly clear.


3. Passing by Reference (&$var)

By default, PHP passes function arguments by value — modifying a parameter inside the function doesn't affect the outer variable. Add & to pass by reference:

PHP
<?php
// Pass by value (default): internal modification doesn't affect the outside
function addTen(int $n): void {
    $n += 10;
}
$x = 5;
addTen($x);
echo $x;  // 5 (unchanged)

// Pass by reference: internal modification directly affects the outer variable
function addTenRef(int &$n): void {
    $n += 10;
}
addTenRef($x);
echo $x;  // 15 (changed!)
?>
Pass by Value Pass by Reference
Syntax function f($x) function f(&$x)
Internal modification Doesn't affect outer variable Affects the outer variable
Best for Most situations When you need to "return" multiple values
⚠️ Warning: Passing by reference makes function behavior "opaque" — the caller doesn't know their variable was changed. Using a return value is usually clearer. Only use references when you must modify the original array in place (e.g., sort(&$arr)).


4. Variable Scope

In PHP, the inside of a function and the outside are two separate worlds:

PHP
<?php
$globalVar = "I'm outside";

function test(): void {
    // echo $globalVar;  // Warning: Undefined variable
    // Functions can't directly access outer variables

    $localVar = "I'm inside";
    echo $localVar;  // OK
}

test();
// echo $localVar;  // Warning: can't access the function's inner variable either
?>

(1) Using global to Break the Barrier

PHP
<?php
$counter = 0;

function increment(): void {
    global $counter;  // Declare: I want to use the global variable
    $counter++;
}

increment();
increment();
echo $counter;  // 2
?>

(2) The $GLOBALS Superglobal Array

PHP
<?php
$name = "John";

function showName(): void {
    echo $GLOBALS['name'];  // John
}
showName();
?>
💡 Tip: The global keyword is a necessary evil — know it exists, but avoid using it whenever possible. Global variables make code hard to test and maintain. Most of the time, pass data into functions as parameters.


5. Static Variables

A static variable inside a function retains its value between calls:

PHP
<?php
function getNextId(): int {
    static $id = 0;
    $id++;
    return $id;
}

echo getNextId();  // 1
echo getNextId();  // 2
echo getNextId();  // 3

// A static variable is only initialized once — on the first call
// Subsequent calls preserve the previous value
?>
💡 Tip: Static variables are useful for caching computed results (avoiding recalculation) or generating unique IDs. But don't use them as a substitute for class properties — that's what object-oriented programming is for.


6. Anonymous Functions (Closures)

Functions don't need names — they can be assigned to variables and passed as arguments:

PHP
<?php
// Anonymous function assigned to a variable
$greet = function(string $name): string {
    return "Hello, {$name}!";
};

echo $greet("John");  // Hello, John!

// Passed as an argument to another function (callback)
$numbers = [1, 2, 3, 4, 5];
$doubled = array_map(function($n) {
    return $n * 2;
}, $numbers);
print_r($doubled);  // [2, 4, 6, 8, 10]
?>

(1) The use Keyword for Anonymous Functions

If an anonymous function needs an outer variable, you must import it with use:

PHP
<?php
$prefix = "User";

// ❌ Wrong: $prefix is not visible inside the anonymous function
// $greet = function($name) {
//     return "{$prefix}: {$name}";
// };

// ✅ Correct: import the outer variable with use
$greet = function($name) use ($prefix): string {
    return "{$prefix}: {$name}";
};

echo $greet("John");  // User: John

// Import by reference (allows modifying the outer variable)
$count = 0;
$inc = function() use (&$count): void {
    $count++;
};
$inc(); $inc();
echo $count;  // 2
?>

7. Arrow Functions (PHP 7.4+)

Arrow functions fn() => are the ultra-concise version of single-expression anonymous functions. They automatically capture outer variables (no use needed):

PHP
<?php
$factor = 3;

// Anonymous function syntax
$anon = function($n) use ($factor) {
    return $n * $factor;
};

// Arrow function syntax (automatically captures $factor)
$arrow = fn($n) => $n * $factor;

echo $anon(5);   // 15
echo $arrow(5);  // 15

// The golden pair with array_map
$nums = [1, 2, 3, 4, 5];
$tripled = array_map(fn($n) => $n * $factor, $nums);
print_r($tripled);  // [3, 6, 9, 12, 15]
?>
💡 Tip: Arrow functions can only contain a single expression (no multi-line logic). They automatically capture outer variables by value. They're perfect for simple map / filter / usort callbacks.


8. Callbacks and the callable Type

PHP lets you use function name strings, anonymous functions, and object methods as callbacks:

PHP
<?php
// Method 1: function name as a string
function double(int $n): int {
    return $n * 2;
}
$result = array_map('double', [1, 2, 3]);
// 'double' (with quotes) — the function name string is passed to array_map

// Method 2: anonymous function
$result = array_map(fn($n) => $n * 3, [1, 2, 3]);

// Method 3: callable type declaration
function apply(callable $fn, array $data): array {
    return array_map($fn, $data);
}

$result = apply('double', [1, 2, 3]);          // ✅
$result = apply(fn($n) => $n * 2, [1, 2, 3]);  // ✅
// apply(123, [1, 2, 3]);  // TypeError!
?>

▶ Example: Closure with use for Tax Calculation

Output:

TEXT 📖 Display only
value
value
PHP
<?php
function makeTaxCalculator(float $rate): callable {
    return function(float $price) use ($rate): float {
        return round($price * (1 + $rate), 2);
    };
}

$taxUK = makeTaxCalculator(0.20);
$taxJP = makeTaxCalculator(0.10);

echo $taxUK(100);  // 120
echo $taxJP(100);  // 110

Output:

TEXT 📖 Display only
Output displayed

❓ FAQ

Q How many meanings does ... have in PHP?
A Two. (1) In a function definition, ...$args packs remaining arguments into an array. (2) At a function call, ...$arr spreads an array into individual arguments. sum(...$nums) is spreading; function sum(...$nums) is packing.
Q Do named arguments break argument order? Can I mix positional and named arguments?
A You can mix them. The rule: named arguments must come after positional ones. foo(1, c: 3, b: 2) is valid; foo(a: 1, 2, 3) is not.
Q When should I use anonymous functions vs. arrow functions?
A Use arrow functions fn($x) => $x * 2 for single expressions. Use anonymous functions function($x) { ... } for multi-line logic. Arrow functions are more concise and auto-capture outer variables (no use needed).

📖 Summary

📝 Exercises

  1. Write a function average(...$numbers): float that takes any number of numeric arguments and returns their average.
  2. Use array_map and an arrow function to convert every string in an array to uppercase.
  3. Use a static variable to write a hitCounter() function that returns an incrementing visit count on each call.
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏