User-defined Functions
What Is a User-defined Function? In simple terms: A user-defined function is a function you create yourself to package a task under a name, so you can run that task whenever you need it by calling the
What Is a User-defined Function?
In simple terms: A user-defined function is a function you create yourself to package a task under a name, so you can run that task whenever you need it by calling the name.
Technically: A user-defined function is declared with the function keyword, followed by a name, a parameter list in parentheses, an optional return type, and a body in curly braces. Once declared, it can be called from anywhere in the script (for top-level functions) like any built-in function.
Syntax
function functionName(Type $parameter1, Type $parameter2): ReturnType
{
// statements
return $value;
}
The Simplest Function
<?php
function sayHello(): void
{
echo "Hello from a function!\n";
}
sayHello();
sayHello();
Output
Hello from a function!
Hello from a function!
How It Works
function sayHello()declares the function. Nothing runs at this point.sayHello();calls it. PHP jumps into the body, runs it, and comes back to the line after the call.- The function can be called as many times as needed.
: voiddeclares that the function does not return a value.
A Function With Parameters and a Return Value
<?php
function rectangleArea(float $width, float $height): float
{
return $width * $height;
}
$room = rectangleArea(4.5, 3.2);
$hall = rectangleArea(6, 5);
echo "Room: {$room} m²\n";
echo "Hall: {$hall} m²\n";
echo "Total: " . ($room + $hall) . " m²\n";
Output
Room: 14.4 m²
Hall: 30 m²
Total: 44.4 m²
Step by Step
- When
rectangleArea(4.5, 3.2)is called, the parameter$widthreceives4.5and$heightreceives3.2. - The body calculates the product.
returnsends the result back; the call expressionrectangleArea(4.5, 3.2)is replaced by that value.- The returned value is stored in
$roomand used later.
rectangleArea(6, 5) passes integers; because the parameters are declared float, PHP converts them to 6.0 and 5.0, and the result is 30.0 (printed as 30).
Naming Functions
Rules
- Must start with a letter or underscore, followed by letters, digits, or underscores.
- No
$prefix. - Case-insensitive, but always call functions with the same case as their declaration.
- Must be unique — a function cannot be declared twice.
Conventions
| Pattern | Use For | Examples |
|---|---|---|
| Verb or verb phrase | Functions that do something | sendEmail(), calculateTotal(), formatDate() |
is/has/can prefix | Functions that return bool | isValidEmail(), hasDiscount(), canEdit() |
get/find prefix | Functions that retrieve data | getUserName(), findOrderById() |
| camelCase or snake_case | Follow your project's standard | formatPrice() or format_price() |
A good function name describes what the function achieves, so the caller does not need to read its body.
Practical Examples
Formatting
<?php
function formatPrice(float $amount, string $symbol = '₹'): string
{
return $symbol . number_format($amount, 2);
}
echo formatPrice(1499.5) . "\n";
echo formatPrice(25, '$') . "\n";
Output
₹1,499.50
$25.00
Validation
<?php
function isValidPincode(string $pincode): bool
{
return preg_match('/^[1-9][0-9]{5}$/', $pincode) === 1;
}
foreach (['600042', '060042', '6000', '56001A'] as $pin) {
echo $pin . ': ' . (isValidPincode($pin) ? 'valid' : 'invalid') . "\n";
}
Output
600042: valid
060042: invalid
6000: invalid
56001A: invalid
Indian PIN codes have six digits and do not start with zero. The regular expression ^[1-9][0-9]{5}$ checks exactly that: one non-zero digit followed by five digits, with nothing before or after. preg_match() returns 1 for a match, so the comparison === 1 turns the result into a real boolean. Regular expressions are covered in the PHP RegEx section.
Transformation
<?php
function initials(string $fullName): string
{
$words = preg_split('/\s+/', trim($fullName));
$letters = array_map(fn(string $word) => mb_strtoupper(mb_substr($word, 0, 1)), $words);
return implode('', $letters);
}
echo initials('karthik raja') . "\n";
echo initials(' Anitha Devi Kumar ') . "\n";
Output
KR
ADK
preg_split('/\s+/', ...) splits on any run of whitespace, so extra spaces between words do not create empty entries.
return Ends the Function
return immediately exits the function. Code after an executed return does not run:
<?php
function discountPercent(float $cartTotal): int
{
if ($cartTotal >= 5000) {
return 15;
}
if ($cartTotal >= 2000) {
return 10;
}
return 0;
}
echo discountPercent(6200) . "%\n";
echo discountPercent(2500) . "%\n";
echo discountPercent(800) . "%\n";
Output
15%
10%
0%
Each return handles one case, and the final return 0 covers everything else. This "early return" style avoids else blocks and nested conditions. Return values are covered in depth in Return Values.
Functions Should Do One Thing
A function that does many things is hard to name, test, and reuse. Compare:
One Function Doing Everything
function processOrder(array $order): void
{
// validate the order
// calculate totals and tax
// save to the database
// send a confirmation email
// print an HTML receipt
}
Small Functions With Single Responsibilities
function validateOrder(array $order): array { /* returns errors */ }
function calculateTotals(array $order): array { /* returns subtotal, tax, total */ }
function saveOrder(array $order, array $totals): int { /* returns order ID */ }
function sendConfirmation(int $orderId, string $email): void { /* sends email */ }
Each small function can be understood, tested, and changed on its own, and processOrder() becomes a short list of calls to them. A practical guideline: if you need the word "and" to describe what a function does, it may be doing too much.
Documenting Functions
A DocBlock above a function describes its purpose, parameters, return value, and possible exceptions, and editors display it when the function is used:
/**
* Calculates GST for an amount, rounded to the nearest paisa.
*
* @param float $amount Amount before tax, in rupees
* @param float $ratePercent GST rate, for example 5, 12, 18, or 28
* @return float GST amount in rupees
*/
function calculateGst(float $amount, float $ratePercent = 18): float
{
return round($amount * $ratePercent / 100, 2);
}
Native types already document the types; the DocBlock adds meaning (units, allowed values). See PHP Multiline Comments.
Organizing Functions in Files
As a project grows, keep reusable functions in dedicated files instead of copying them into every page:
project/
├── src/
│ ├── helpers.php ← formatPrice(), initials(), ...
│ └── validation.php ← isValidPincode(), isValidEmail(), ...
└── public/
└── index.php
<?php
// public/index.php
require_once __DIR__ . '/../src/helpers.php';
require_once __DIR__ . '/../src/validation.php';
echo formatPrice(999);
require_once loads each file only once, even if several files require it, which prevents "Cannot redeclare" errors. In Composer-based projects, helper files are listed under autoload.files in composer.json and loaded automatically. Includes are covered in PHP Include and Composer in Composer.
Guarding Against Redeclaration
Libraries sometimes wrap helper functions in a check so that two copies of the same helper do not collide:
<?php
if (!function_exists('formatPrice')) {
function formatPrice(float $amount): string
{
return '₹' . number_format($amount, 2);
}
}
echo formatPrice(50);
Output
₹50.00
For your own code, loading each file once with require_once (or using namespaces) is the cleaner solution.
Pure Functions and Side Effects
A pure function depends only on its parameters and only produces a return value — it does not read or change anything outside itself. rectangleArea() and formatPrice() are pure.
A function with side effects changes something outside itself: it prints output, writes to a file or database, sends an email, or modifies a global variable.
| Pure Functions | Functions With Side Effects |
|---|---|
| Same input → always the same output | Result may depend on external state |
| Easy to test | Need setup (database, files) to test |
| Safe to call any number of times | Calling twice may send two emails |
Side effects are necessary — applications must save data and send responses — but keeping calculations in pure functions and isolating side effects in a few clearly named functions makes code much easier to reason about.
Common Mistakes
Declaring the Same Function Twice
Effect: Fatal error: "Cannot redeclare ...", often caused by including the same file twice.
Fix: Use require_once, unique names, or namespaces.
Forgetting return
<?php
function add(int $a, int $b): int
{
$sum = $a + $b;
}
Effect: Calling add(2, 3) throws a TypeError ("Return value must be of type int, none returned"), because the function is declared to return int but returns nothing. Without a return type, it would silently return null.
Fix: return $sum; — and declare return types so the mistake is caught.
Code After return
Effect: Statements after an executed return never run.
Fix: Put all work before the return.
Echoing Inside Calculation Functions
Effect: Output appears in unexpected places, and results cannot be reused.
Fix: Return values; output them at the call site.
Best Practices
- Choose names that describe the result or action: verbs for actions,
is/hasfor booleans. - Keep functions small and focused on one responsibility.
- Declare parameter types and return types.
- Prefer pure functions for calculations; isolate side effects.
- Store shared functions in included files or autoloaded files, not copied between pages.
Official reference: https://www.php.net/manual/en/functions.user-defined.php