Functions in PHP
Learn how to define and use functions in PHP - parameters, return values, default and named arguments, scope, recursion, closures, and arrow functions with Docker-ready examples
Functions are the building blocks of reusable code. They let you package a piece of logic behind a name, call it as many times as you need, and pass data in and out cleanly. Instead of repeating the same lines throughout a script, you write the logic once and invoke it wherever required.
PHP is a multi-paradigm language, and its function support reflects that. You can write plain procedural functions in the C tradition, attach type hints for safety, take advantage of default and named arguments, and treat functions as first-class values for a functional style. Because PHP is dynamically and weakly typed, type declarations on parameters and return values are optional — but they make code far easier to reason about and are standard practice in modern PHP.
In this tutorial you’ll learn how to define functions, pass parameters and return values, use default and named arguments, understand variable scope, write recursive functions, and work with PHP’s first-class functions: closures and arrow functions.
Defining and Calling Functions
A function is declared with the function keyword, a name, a parameter list, and a body. Modern PHP lets you add type declarations for parameters and a return type after the parameter list.
Create a file named functions.php:
| |
The declare(strict_types=1) line at the top enforces strict type checking, so passing a string where an int is expected raises an error instead of silently coercing the value. The void return type documents that a function returns no useful value.
Default and Named Arguments
PHP lets you give parameters default values, making them optional when calling the function. Since PHP 8.0, you can also pass arguments by name, which makes calls self-documenting and lets you skip optional parameters without listing every one before them.
Create a file named arguments.php:
| |
When you call makeMessage("Ada"), the two defaults fill in automatically. Named arguments (punctuation: "...") let you target a specific optional parameter while leaving the others at their defaults.
Variable Scope
Variables defined inside a function are local to that function and don’t leak into the surrounding code. Likewise, functions can’t see variables from the outer scope unless you explicitly bring them in with the global keyword or pass them as arguments. PHP also supports static local variables that retain their value between calls.
Create a file named scope.php:
| |
The first echo inside showScope() prints the local value. After global $message, the function rebinds $message to the global variable, so the second echo prints the global text. The counter() function uses a static variable that survives between calls, incrementing each time.
Recursion
A recursive function calls itself to solve a problem by breaking it into smaller subproblems. Every recursive function needs a base case to stop the recursion. The classic example is computing a factorial.
Create a file named recursion.php:
| |
factorial(5) expands to 5 * 4 * 3 * 2 * 1 = 120, and factorial(10) is 3628800. The fibonacci() function calls itself twice per step, building the familiar sequence starting from 0 and 1.
Higher-Order Functions, Closures, and Arrow Functions
In PHP, functions are first-class values. You can store them in variables, pass them as arguments, and return them from other functions. An anonymous function (closure) is created with function () { ... } and can capture outer variables with use. PHP 7.4 introduced arrow functions (fn () => ...), which capture outer variables automatically and are ideal for short callbacks.
Create a file named closures.php:
| |
array_map and array_filter are higher-order functions: they take another function as an argument. The arrow function fn (int $n): int => $n * $n is shorthand that automatically captures $numbers from the surrounding scope. makeMultiplier() returns a closure that remembers its $factor, demonstrating how functions can produce other functions.
Running with Docker
| |
Expected Output
Running functions.php:
Hello from a function!
3 + 4 = 7
Now presenting: PHP Functions
Running arguments.php:
Hello, Ada!
Welcome, Grace!
Hello, Linus...
Is it you, Margaret?
Running scope.php:
I live inside the function
I live in the global scope
Call 1: 1
Call 2: 2
Call 3: 3
Running recursion.php:
5! = 120
10! = 3628800
First 10 Fibonacci numbers: 0 1 1 2 3 5 8 13 21 34
Running closures.php:
Square of 6: 36
4 times 3: 12
Squares: 1, 4, 9, 16, 25
Evens: 2, 4
Double 7: 14
Triple 7: 21
Key Concepts
- Type declarations are optional but recommended — PHP is dynamically and weakly typed, but adding parameter and return types (with
declare(strict_types=1)) catches errors early and documents intent. - Default values make parameters optional — give a parameter a default and callers can omit it entirely.
- Named arguments improve readability — since PHP 8.0 you can pass arguments by name in any order and skip optional ones.
- Local scope is the default — variables inside a function don’t leak out, and outer variables aren’t visible unless passed in, declared
global, or captured withuse. staticlocals persist between calls — useful for counters and memoization without polluting the global scope.- Recursion needs a base case — every recursive function must have a stopping condition to avoid infinite loops.
- Functions are first-class values — store them in variables, pass them to higher-order functions like
array_mapandarray_filter, and return them from other functions. - Arrow functions capture scope automatically —
fn () => ...is concise and binds outer variables for you, while full closures useusefor explicit capture.
Running Today
All examples can be run using Docker:
docker pull php:8.4-cli-alpine
Comments
Loading comments...
Leave a Comment