Functions
By the end of this lesson you'll write reusable PHP functions with typed parameters and return types, default and named arguments, variadics, references, and arrow functions and closures — the building blocks of every program bigger than a script.
Part of the free Php course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
1️⃣ Defining, Calling & Returning
A function is a named block of code you can run on demand. You define it once with the function keyword, then call it by writing its name followed by () . A parameter is an input slot in the definition; an argument is the actual value you pass when calling. The keyword return hands a value back to whoever called the function — that's different from echo , which only prints. A return type like : string after the ) documents and enforces what comes back; : void means "returns nothing".
The declare(strict_types=1); line at the top makes PHP strict about types — pass a string where an int is expected and you get a clear error instead of a silent conversion. Put it at the very top of every file; it's a best-practice habit that catches bugs early.
2️⃣ Typed Parameters, Defaults & Named Arguments
Types in front of a parameter ( string $name ) say what kind of value is allowed. A default value ( $role = "Student" ) makes a parameter optional — leave it out and the default is used. A nullable type ?string means "a string or null ", and a union type int|string (PHP 8) means "either of these". With named arguments (PHP 8) you pass values by parameter name — introduce(role: "Mentor", name: "Carol") — so order stops mattering and your calls read like documentation.
3️⃣ Variadics & Pass-by-Reference
Sometimes you don't know how many arguments you'll get. A variadic parameter int ...$numbers collects every extra argument into one array, so sum(1, 2, 3) and sum(10, 20, 30, 40) both work. By default PHP passes a copy of each argument, so changing a parameter inside a function leaves the caller's variable untouched. Put an ampersand in front — &$total — to pass by reference instead, letting the function edit the original directly. Use references sparingly; usually returning a value is clearer.
4️⃣ Arrow Functions, Closures & Scope
PHP also lets you store a function in a variable — an anonymous function with no name. An arrow function fn($x) => $x * 2 (PHP 7.4+) is the short form: a single expression that automatically grabs any outer variables it mentions. A closure function ($x) use ($y) { ... } can hold a full multi-line body but must explicitly list outer variables in its use () clause. This matters because every function has its own scope : it can't see variables defined outside it unless you pass them in, capture them, or pull a global in with the global keyword.
5️⃣ Your Turn
Now you write the missing pieces. The script below is almost complete — fill in each ___ using the 👉 hint, then run it and check it against the Output panel.
One more — this time finishing an arrow function and a closure that needs to capture a variable.
Common Errors (and the fix)
- Your function returns null instead of a value — you forgot return , or you echo 'd the value inside the function instead of returning it. A function that never hits a return gives back null . Add a return type like : int so PHP flags the mistake instead of failing silently.
- "TypeError: ... must be of type int, string given" — with declare(strict_types=1) at the top, passing the wrong type is an error, not a quiet conversion. Pass the right type, or change the parameter to a union like int|string if both are genuinely valid.
- "Undefined variable" inside a function — functions have their own scope and can't see outer variables. Pass the value in as a parameter, or use global $name; for a program-wide value. Variables defined outside simply don't exist inside unless you bring them in.
- Your change inside a function "didn't stick" — PHP passes arguments by value (a copy) by default, so editing a parameter doesn't touch the caller's variable. If you really need to modify the original, declare the parameter by reference with &$x — otherwise return the new value and assign it.
- "Cannot use positional argument after named argument" — once you start naming arguments in a call, every following argument must also be named. Either name them all, or keep the unnamed ones first: f("Carol", role: "Mentor") .
Pro Tips
- 💡 Always add type hints and a return type. They catch bugs early and act as built-in documentation — the reader knows exactly what goes in and what comes out.
- 💡 Prefer parameters and return values over global and references. Functions that only touch their inputs and outputs are far easier to test and reason about.
- 💡 Reach for fn() for one-line callbacks in array_map / array_filter , and a full closure with use when the body needs more than one expression.
📋 Quick Reference — PHP Functions
Feature
Example
Since
Definition
function f($x) { ... }
PHP 4
Typed param & return
function f(int $x): string
PHP 7.0
Default value
function f($x = 10)
Nullable type
?string
PHP 7.1
Variadic
function f(int ...$nums)
PHP 5.6
By reference
function f(&$x)
Arrow function
fn($x) => $x * 2
PHP 7.4
Closure
function ($x) use ($y) {}
PHP 5.3
Union type
int|string
PHP 8.0
Named arguments
f(name: "Carol")
Frequently Asked Questions
Mini-Challenge: Shopping-Cart Total
No code is filled in this time — just a brief and an outline. Write it yourself, run it on onecompiler.com/php or your own machine, then check your result against the expected output in the comments. This combines a variadic function, a return type, and a helper that formats the result.
🎉 Lesson Complete!
- ✅ Define a function with function , call it with () , and hand back a value with return
- ✅ Type parameters and returns — int , ?string , array , void , and union int|string
- ✅ Make parameters optional with defaults and call clearly with PHP 8 named arguments
- ✅ Accept any number of inputs with a variadic ...$args
- ✅ Edit a caller's variable with pass-by-reference &$x (and know when not to)
- ✅ Store functions in variables with fn() => and use closures, and manage scope with global
- ✅ Next lesson: Arrays & Collections — store and process lists of values, PHP's most-used data structure
Practice quiz
Which keyword hands a value back to the caller of a function?
- echo
- return
- give
Answer: return. return hands a value back; echo only prints and does not return anything usable.
What does the return type : void mean?
- The function returns nothing
- Returns an empty string
- Returns null only
- The function never ends
Answer: The function returns nothing. : void declares that the function returns no value.
What does a function return if it reaches the end without a return statement?
- 0
- An empty string
- It throws an error
- null
Answer: null. A function with no return (or a bare return;) gives back null.
What does the nullable type ?string mean for a parameter?
- A string that cannot be null
- A string OR null
- An array of strings
- An optional integer
Answer: A string OR null. ?string means the value may be a string or null.
What does a variadic parameter like int ...$numbers do?
- Collects all extra arguments into an array
- Requires exactly one argument
- Passes by reference
- Makes the parameter optional only
Answer: Collects all extra arguments into an array. A variadic parameter gathers every extra argument into a single array.
By default, how does PHP pass arguments to a function?
- By reference
- As global variables
- By value (a copy)
- As constants
Answer: By value (a copy). PHP passes a copy by default, so editing a parameter doesn't change the caller's variable.
What does the & in a parameter like &$total enable?
- A default value
- Pass by reference, so the function can change the original
- A union type
- A variadic
Answer: Pass by reference, so the function can change the original. An ampersand passes by reference, letting the function modify the caller's variable in place.
How does an arrow function fn($x) => $x * $factor capture $factor?
- It cannot use outer variables
- Only via a use() clause
- Only if it is global
- Automatically from the surrounding scope
Answer: Automatically from the surrounding scope. Arrow functions automatically capture variables from the enclosing scope.
How does a closure (function ($x) { ... }) capture an outer variable?
- Automatically
- By listing it in a use () clause
- It cannot
- By marking it readonly
Answer: By listing it in a use () clause. A closure must explicitly list captured variables in its use () clause.
What lets named arguments like introduce(role: "Mentor", name: "Carol") work?
- They must be in declaration order
- They require references
- Order no longer matters because you pass by parameter name
- They only work for one argument
Answer: Order no longer matters because you pass by parameter name. Named arguments (PHP 8) pass by parameter name, so the order stops mattering.
Continue this course
- Previous: Loops
- Next: Arrays & Collections