Skip to content

PHP Fundamentals for OOP

Object-oriented PHP still depends on the language’s basic runtime and type rules. These foundations let us understand what values an object can hold, what a method accepts, and when PHP reports an invalid call.

PHP is dynamically typed. A variable name can refer to values of different types during execution:

$value = 10; // int
$value = 'ten'; // string

The second assignment replaces the first value. PHP still has real types; they belong to the current value rather than being permanently attached to the variable name. get_debug_type($value) reports the current type.

Common types include int, float, string, bool, array, object, and null.

A function gives behavior a name and can define its accepted inputs and result:

function calculateTotal(int $price, int $quantity): int
{
return $price * $quantity;
}
$total = calculateTotal(20, 3);

$price and $quantity are parameters in the function definition. 20 and 3 are arguments supplied by the caller.

return sends a value back to the caller. echo only writes output; it does not return the displayed value.

Arrays may use numeric indexes or named keys:

$prices = [100, 50, 25];
$order = [
'id' => 15,
'status' => 'pending',
];

Control-flow statements such as if, elseif, else, match, and loops choose which operations execute. They also help a function handle the valid cases declared by its types.

Arrays are useful, but later lessons will show why an object may be a better home when data has rules and behavior that must remain together.

Add this declaration at the beginning of a PHP file:

<?php
declare(strict_types=1);

Without it, PHP may coerce compatible scalar arguments. For example, a numeric string may be converted to an integer. With strict typing, passing a string to an int parameter throws a TypeError:

declare(strict_types=1);
function double(int $number): int
{
return $number * 2;
}
double('10'); // TypeError

For argument checking, the strict_types mode of the calling file is what matters. PHP still permits an int where a float is expected because this widening conversion does not lose the integer value.

A nullable type permits either the named type or null:

function findCustomerEmail(int $customerId): ?string
{
// Return an email address or null.
}

?string is shorthand for string|null. The caller must understand what null means; using the same null result for several failure cases may be ambiguous.

A union lists several accepted types:

function normalizeId(int|string $id): string
{
return (string) $id;
}

This accepts int or string, but not null. If absence is valid, it must be declared explicitly as int|string|null.

PHP first parses and compiles a file into internal instructions called opcodes, then executes those instructions.

  • Invalid PHP grammar produces a syntax or parse error before normal execution.
  • Calling a typed function with an invalid value produces a TypeError when that call executes at runtime.

The following code has valid syntax, but the call fails at runtime:

declare(strict_types=1);
function pay(int $amount): void
{
echo $amount;
}
pay('100'); // TypeError
<?php
declare(strict_types=1);
function calculateFinalPrice(float $price, ?float $discount): float
{
if ($discount === null) {
return $price;
}
return $price - $discount;
}

The signature documents the contract, while the control flow handles every declared input case. In PHP-only files, the closing ?> tag is normally omitted to avoid accidental output after it.

  • Assuming dynamically typed means PHP has no types.
  • Confusing parameters with arguments.
  • Using echo when the caller needs a returned value.
  • Expecting strict_types to validate data before a call executes.
  • Calling a runtime TypeError a syntax error.
  • Forgetting to include null in a type when absence is a valid result.
  • Using a broad union when a clearer domain model would express the meaning better.

PHP variables can refer to values of different types, while function and method declarations define explicit contracts. strict_types, nullable types, and union types make those contracts clearer. Syntax is checked before normal execution, while an invalid typed call usually fails with TypeError when the call runs.

  1. What is the difference between a parameter and an argument?
  2. Why does echo not replace return?
  3. What does ?string permit?
  4. Why is an invalid argument type a runtime error rather than a syntax error?