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 example
<?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 example
<?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 example
<?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 example
<?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 example
<?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 TypeError in a small example;
  • use nullable types only when null is 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:

PHP example
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 example
<?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 example
<?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 example
<?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:

PHP example
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 example
<?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.