PHP Functions — Declaration, Parameters, Return Types, and Scope
In this tutorial, you will learn about PHP Functions. We cover key concepts, practical examples, and best practices to help you master this topic.
PHP functions are reusable blocks of code that accept parameters, return values, and follow strict type rules when declared with PHP 8's type system, enabling modular and testable application design.
Why It Matters
Functions are the primary unit of code organization in PHP. A well-written function does one thing, does it well, and can be tested independently. Without functions, you repeat code, making maintenance harder and bugs more likely. PHP's type system, introduced gradually from PHP 5 through PHP 8, lets you declare exactly what types a function expects and returns, catching errors before they reach production.
Real-World Use
Laravel uses functions extensively -- helper functions like collect(), tap(), and dd() are defined as global functions. WordPress has thousands of functions for database queries, template rendering, and plugin hooks. REST API handlers in Symfony are methods that accept typed request objects and return typed responses. DodaTech's PHP tools use typed functions with strict mode enabled for reliable data processing.
What You Will Learn
- Declaring functions with parameters and return types
- Type declarations for parameters and return values
- Default parameter values and named arguments
- Variadic functions and spread operators
- Anonymous functions and closures
- Variable scope and static variables in functions
- Strict type mode and its benefits
Learning Path
flowchart LR A[Control Flow] --> B[Functions
You are here] B --> C[Arrays] C --> D[Superglobals] D --> E[Forms] style B fill:#f90,color:#fff
Basic Function Declaration
A function is declared with the function keyword, a name, optional parameters, and a body:
<?php
function greet($name) {
return "Hello, $name!";
}
echo greet("Alice"); // Hello, Alice!
Function Naming Rules
- Function names are case-insensitive (but use consistent casing)
- Must start with a letter or underscore
- Use descriptive names:
calculateTotal()notcalc() - Follow PSR-1 naming: functions use camelCase
Type Declarations
PHP 7+ supports type declarations for parameters and return values:
<?php
function add(int $a, int $b): int {
return $a + $b;
}
echo add(5, 3); // 8
echo add(5, "3"); // 8 (string converted to int)
With strict types enabled, PHP throws a TypeError if the types do not match:
<?php
declare(strict_types=1);
function add(int $a, int $b): int {
return $a + $b;
}
echo add(5, "3"); // TypeError: Argument 2 must be int, string given
Available Type Declarations
| Type | Description |
|---|---|
int |
Integer |
float |
Floating-point number |
string |
String |
bool |
Boolean |
array |
Array |
object |
Object |
mixed |
Any type (PHP 8+) |
void |
No return value |
never |
Never returns (exit, die) |
?type |
Nullable type (type or null) |
int\|string |
Union type (PHP 8+) |
Nullable Types and Union Types
Nullable types accept a value or null:
<?php
function findUser(int $id): ?array {
$users = [
1 => ['name' => 'Alice'],
2 => ['name' => 'Bob'],
];
return $users[$id] ?? null;
}
$user = findUser(1); // ['name' => 'Alice']
$user = findUser(3); // null
Union types accept multiple types (PHP 8+):
<?php
function formatValue(int|string $value): string {
if (is_int($value)) {
return "Number: $value";
}
return "String: $value";
}
echo formatValue(42); // Number: 42
echo formatValue("hello"); // String: hello
Default Parameter Values
Parameters can have default values that make them optional:
<?php
function createUser(string $name, string $role = 'user', bool $active = true): array {
return [
'name' => $name,
'role' => $role,
'active' => $active,
];
}
print_r(createUser('Alice'));
print_r(createUser('Bob', 'admin'));
print_r(createUser('Charlie', 'editor', false));
Required parameters must come before optional ones.
Named Arguments
PHP 8 introduced named arguments, letting you skip default parameters:
<?php
function createProfile(string $name, string $email, string $phone = '', string $bio = ''): void {
echo "Creating profile for $name ($email)\n";
}
// Skip phone, provide bio
createProfile(name: 'Alice', email: 'alice@example.com', bio: 'PHP developer');
Named arguments make function calls self-documenting. You can reorder arguments or skip optional ones.
Variadic Functions and Spread Operator
Accept a variable number of arguments with ...:
<?php
function sum(int ...$numbers): int {
return array_sum($numbers);
}
echo sum(1, 2, 3, 4, 5); // 15
The spread operator unpacks an array into arguments:
<?php
$numbers = [1, 2, 3, 4, 5];
echo sum(...$numbers); // 15
Return Type Void and Never
Functions that do not return a value use void:
<?php
function logMessage(string $message): void {
file_put_contents('log.txt', $message . PHP_EOL, FILE_APPEND);
// No return statement needed
}
PHP 8.1 introduced never for functions that terminate execution:
<?php
function redirect(string $url): never {
header("Location: $url");
exit;
}
Anonymous Functions (Closures)
Anonymous functions have no name and can be assigned to variables or passed as arguments:
<?php
$greet = function(string $name): string {
return "Hello, $name!";
};
echo $greet("Alice"); // Hello, Alice!
// Passing to array_map
$numbers = [1, 2, 3, 4, 5];
$doubled = array_map(function($n) { return $n * 2; }, $numbers);
print_r($doubled);
Expected output:
Array
(
[0] => 2
[1] => 4
[2] => 6
[3] => 8
[4] => 10
)
Capturing Variables with Use
Closures can capture variables from the surrounding scope:
<?php
$prefix = "User: ";
$formatUser = function(string $name) use ($prefix): string {
return $prefix . $name;
};
echo $formatUser("Alice"); // User: Alice
By default, captured variables are passed by value. Use & to capture by reference.
Arrow Functions
PHP 7.4 introduced arrow functions for simple closures:
<?php
$numbers = [1, 2, 3, 4, 5];
$doubled = array_map(fn($n) => $n * 2, $numbers);
// Arrow functions automatically capture variables by value
$factor = 3;
$tripled = array_map(fn($n) => $n * $factor, $numbers);
Arrow functions can only contain a single expression. They implicitly capture parent scope variables by value.
Variable Functions
If you append parentheses to a variable containing a function name, PHP calls that function:
<?php
function sayHello(): void {
echo "Hello!\n";
}
function sayGoodbye(): void {
echo "Goodbye!\n";
}
$func = 'sayHello';
$func(); // Hello!
$func = 'sayGoodbye';
$func(); // Goodbye!
Common Mistakes
1. Not Returning a Value
function getUserName() {
echo "Alice"; // Prints, but does not return
}
$name = getUserName(); // $name is null
Use return to send a value back to the caller.
2. Modifying Global Variables Inside Functions Unexpectedly
$count = 0;
function increment(): void {
global $count;
$count++;
}
Be explicit with global or pass parameters. Prefer parameters and return values.
3. Forgetting to Declare Strict Types
function calculate(int $a, int $b): int {
return $a + $b;
}
echo calculate("5", 3); // 8 with weak types, no error
Add declare(strict_types=1) at the top of every file to catch type mismatches.
4. Type Hinting Mixed When Specific Types Are Known
function process(mixed $data): mixed { // Too vague
Be as specific as possible: Process(array $data): string.
5. Not Using Named Arguments for Functions with Many Parameters
createUser('Alice', 'alice@test.com', true, 'admin', 'active');
Use named arguments: createUser(name: 'Alice', role: 'admin').
Practice Questions
How do you declare a function that accepts an array and returns a string?
function formatNames(array $names): string { ... }What is the difference between void and never return types? void returns nothing and execution continues. never terminates execution (exit, throw, die).
How do anonymous functions capture variables from the parent scope? Using the
usekeyword:function() use ($var) { ... }. Arrow functions capture automatically.What happens when strict_types is enabled and you pass a wrong type? PHP throws a TypeError. The script stops unless you catch it.
Challenge: Write a function
applyDiscountthat accepts a float price, a float discount percentage, and optional bool for whether to round, returning the discounted price with proper types.
Mini Project: Utility Library
Create a set of utility functions:
<?php
declare(strict_types=1);
function sanitizeEmail(string $email): string {
return filter_var(trim($email), FILTER_SANITIZE_EMAIL);
}
function validateEmail(string $email): bool {
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
function truncateText(string $text, int $maxLength = 100): string {
if (strlen($text) <= $maxLength) {
return $text;
}
return substr($text, 0, $maxLength - 3) . '...';
}
function arrayToCommaString(array $items, string $separator = ', '): string {
return implode($separator, $items);
}
// Test the functions
$email = sanitizeEmail(" Alice@Example.COM ");
echo "Sanitized: $email\n";
echo "Valid: " . (validateEmail($email) ? 'Yes' : 'No') . "\n";
echo truncateText("This is a very long text that should be cut off", 30) . "\n";
echo arrayToCommaString(['PHP', 'Python', 'JavaScript']) . "\n";
FAQ
What is Next
Now that you understand functions, proceed to Arrays to master PHP's array functions, including array_map, array_filter, array_reduce, and sorting. Then read Superglobals to learn about predefined variables.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro