Parameters, Types, and Return Values
A mail slot shaped for letters won't take a parcel. That's not rudeness; it stops the wrong thing going in. Types give your functions a slot of the right shape.
In Writing Functions, your functions accepted anything. Call addTax("banana") and PHP would happily try. This lesson makes functions easier to call correctly, and harder to call wrongly.
Default values
A parameter can have a default value, used when the caller leaves that argument out:
<?php
function greet($name, $greeting = "Hello") {
return "$greeting, $name!";
}
echo greet("Maria"), "\n";
echo greet("Maria", "Good morning"), "\n";Hello, Maria!
Good morning, Maria!Parameters with defaults are optional. Put them after the required ones. Leaving out a required argument stops the script:
<?php
function greet($name, $greeting = "Hello") {
return "$greeting, $name!";
}
echo greet();
// error: Too few arguments to function greet(), 0 passedNamed arguments
Normally, arguments are matched by position. With named arguments, you write the parameter's name, a colon, then the value. That lets you skip optional parameters, and makes a call easier to read:
<?php
function makeTicket($event, $seats = 1, $isVip = false, $note = "") {
$vip = $isVip ? "VIP " : "";
return "$vip$event x$seats $note";
}
echo makeTicket("Concert", 2, false, "near the stage"), "\n";
echo makeTicket("Concert", note: "near the stage"), "\n";
echo makeTicket(isVip: true, event: "Concert"), "\n";Concert x2 near the stage
Concert x1 near the stage
VIP Concert x1Compare the first two calls. In the first, what does false mean? You'd have to check the definition. The second says exactly what it's setting, and skips the rest. Named arguments can even come in any order.
PHP's own functions accept named arguments too, like str_pad("7", 3, "0", pad_type: STR_PAD_LEFT).
Parameter types
You can write a type before each parameter, so the function only accepts that kind of value:
<?php
declare(strict_types=1);
function area(int $width, int $height) {
return $width * $height;
}
echo area(3, 4), "\n";
echo area("3", 4), "\n";
// error: area(): Argument #1 ($width) must be of type int, string givenThe first call works. The second stops with a clear error: it names the function, the argument, and what went wrong. That's much better than a wrong answer showing up somewhere far away later.
The types you'll use most: int, float, string, bool, and array.
declare(strict_types=1)
That first line, declare(strict_types=1);, matters. Without it, PHP uses type juggling (from Type Juggling and Strict Comparisons) and converts values when it can: area("3", 4) would quietly turn "3" into 3 and return 12. With strict types on, PHP refuses any value of the wrong type.
- It must be the very first statement in the file, right after
<?php. - It applies to the file it's in, for the function calls made in that file.
- There's one small exception: an
intis accepted where afloatis expected, since every whole number is a valid decimal.
Strict types catch mistakes early, so most modern PHP code turns them on. From here on, this track does too.
Return types
After the parentheses, a colon and a type say what the function returns:
<?php
declare(strict_types=1);
function average(int $a, int $b): float {
return ($a + $b) / 2;
}
function sayHi(string $name): void {
echo "Hi, $name!\n";
}
echo average(7, 8), "\n";
sayHi("Ben");7.5
Hi, Ben!: floatpromises the function returns a float. If it tried to return something else, PHP would stop with an error.: voidmeans "returns nothing." It's for functions that just do something, like printing.
What about average(8, 8)? (8 + 8) / 2 is the int 8. Does that break the float promise? No: that's the int-to-float exception again, so PHP converts it, and var_dump(average(8, 8)) shows float(8).
Nullable and union types
Sometimes a value might be missing. Put a ? before a type to also allow null:
<?php
declare(strict_types=1);
function welcome(?string $nickname): string {
return "Welcome, " . ($nickname ?? "friend") . "!";
}
echo welcome("Mimi"), "\n";
echo welcome(null), "\n";Welcome, Mimi!
Welcome, friend!And when a parameter can be one of several types, list them with |, called a union type: int|float $amount accepts either kind of number.
Try it
A delivery app works out a fee. Predict each line, and which call stops the script.
Running PHP here
Running PHP right in the browser is coming to Syntaxia soon. For now, you can read and edit the code here. If you have PHP installed on your computer (see Setting Up), save it as index.php and run it with php index.php.
Check your prediction
Standard 70.00
Rush 105.00
Promo 0.00
Far rush 240.00
Fatal error: Uncaught TypeError: deliveryFee(): Argument #1 ($distanceKm) must be of type float, string given, called in C:\Users\maria\php-practice\index.php on line 23 and defined in C:\Users\maria\php-practice\index.php:4
Stack trace:
#0 C:\Users\maria\php-practice\index.php(23): deliveryFee('5')
#1 {main}
thrown in C:\Users\maria\php-practice\index.php on line 4The int 3 is accepted as a float. Rush multiplies 70 by 1.5 to get 105. The promo sets the fee to 0 (an int, which is fine for a float return). The named arguments come in a different order, which is allowed. The last call passes the string "5", and with strict types on, that stops the script with a TypeError. (Your file path will differ.)
Try it yourself
- Remove the
declare(strict_types=1);line and run it again. What happens to the "Typo" line now? - Add a parameter
int $items = 1todeliveryFee, and charge 5 extra per item after the first. - Write a function
fullName(string $first, string $last, ?string $middle = null): stringthat includes the middle name only when it's given.
Check your understanding
Up next
Why can't a function see a variable you made outside it? That's about scope, the rules for where each variable can be seen, in Variable Scope.
