php language basics
Type Declarations and Strict Types
Type declarations describe what kind of value a function accepts and returns. They make a function contract visible to humans, PHP, and static analysis tools.
Strict types are enabled with declare(strict_types=1); at the top of a PHP file. With strict types, PHP is less willing to quietly convert scalar arguments such as strings to integers. That helps catch mistakes closer to where they happen.
Parameter And Return Types
<?php
declare(strict_types=1);
function applyDiscountCents(int $priceCents, int $discountCents): int
{
return max(0, $priceCents - $discountCents);
}
echo applyDiscountCents(2500, 400) . "\n";
// Prints:
// 2100
The function accepts two integers and returns an integer. A reviewer can understand the unit from the names and the allowed types from the signature.
Strict Types Catch Bad Calls
With strict types enabled, this call raises a TypeError because '2500' is a string, not an integer.
<?php
declare(strict_types=1);
function formatCents(int $cents): string
{
return '£' . number_format($cents / 100, 2);
}
try {
echo formatCents('2500') . "\n";
} catch (TypeError $exception) {
echo "Wrong argument type\n";
}
// Prints:
// Wrong argument type
The fix is not to remove the type. The fix is to validate and convert external input at the boundary, then pass the correct type into the function.
Nullable Types
Use ?type when a value may be that type or null.
<?php
declare(strict_types=1);
function customerLabel(?string $name): string
{
if ($name === null || trim($name) === '') {
return 'Guest';
}
return trim($name);
}
echo customerLabel(null) . "\n";
echo customerLabel(' Ada ') . "\n";
// Prints:
// Guest
// Ada
Only use nullable types when null has a real meaning. Do not use ?string just to avoid deciding what the function requires.
void Return Type
Use void for a function that performs an action and does not return a value.
<?php
declare(strict_types=1);
function printLine(string $message): void
{
echo $message . "\n";
}
printLine('Ready');
// Prints:
// Ready
Prefer returning values for business logic. Use void for clear side-effect functions such as printing, logging, or writing a file.
Boundary Rule
External data often arrives as strings. Query strings, form posts, CSV rows, and environment variables do not automatically become clean integers or booleans.
<?php
declare(strict_types=1);
function parseQuantity(string $value): int
{
if (!ctype_digit($value)) {
throw new InvalidArgumentException('Quantity must contain digits only.');
}
$quantity = (int) $value;
if ($quantity <= 0) {
throw new InvalidArgumentException('Quantity must be positive.');
}
return $quantity;
}
echo parseQuantity('3') . "\n";
// Prints:
// 3
Validate and convert at the boundary. Keep the rest of your code working with clear types.
Common Mistakes
Do not rely on type declarations as validation for user input. They catch wrong PHP values, but they do not check business rules such as "quantity must be positive."
Do not remove return types to make an error disappear. Fix the function so it returns what it promises.
Do not forget that strict_types is declared per file. A file without it may still coerce scalar arguments when it calls a function.
What You Should Be Able To Do
After this lesson, you should be able to:
- add parameter and return types to a function;
- explain what
declare(strict_types=1);changes; - catch a
TypeErrorin a small example; - use nullable types only when
nullis meaningful; - choose between returning a value and using
void; - validate and convert external strings before passing typed values deeper into code.
Practice
Task: Typed Discount
Task
Write a function named applyDiscountCents() with this signature:
function applyDiscountCents(int $priceCents, int $discountCents): int
{
// Write your implementation here.
}
It should return the price after discount, but never below 0.
Call it with 2500 and 400, then print the result.
Show solution
Solution
<?php
declare(strict_types=1);
function applyDiscountCents(int $priceCents, int $discountCents): int
{
return max(0, $priceCents - $discountCents);
}
echo applyDiscountCents(2500, 400) . "\n";
// Prints:
// 2100
Explanation
The signature says the function accepts integers and returns an integer. max(0, ...) prevents the result from becoming negative.
Task: Fix Return Type
Task
Fix this function so it really returns a string:
<?php
declare(strict_types=1);
function formatCents(int $cents): string
{
return $cents;
}
The fixed function should return £12.99 when called with 1299.
Show solution
Solution
<?php
declare(strict_types=1);
function formatCents(int $cents): string
{
return '£' . number_format($cents / 100, 2);
}
echo formatCents(1299) . "\n";
// Prints:
// £12.99
Explanation
The function promises to return string, so it should build and return the formatted label, not the raw integer.
Task: Write Typed Normalizer
Task
Write a function named normaliseRequiredText() with this signature:
function normaliseRequiredText(string $value): string
{
// Write your implementation here.
}
The function should trim the value, throw InvalidArgumentException if the result is empty, and return the cleaned string otherwise.
Call it with ' PHP ' and print the result.
Show solution
Solution
<?php
declare(strict_types=1);
function normaliseRequiredText(string $value): string
{
$value = trim($value);
if ($value === '') {
throw new InvalidArgumentException('Value is required.');
}
return $value;
}
echo normaliseRequiredText(' PHP ') . "\n";
// Prints:
// PHP
Explanation
The function accepts and returns strings, but it still performs a business validation: the cleaned value must not be empty.