Chapter 09 ยท Going Deeper
Static & Constants
Everything so far belonged to individual objects โ each cookie carried its own data.
But some things logically belong to the cutter itself: a counter of how many cookies were
made, a shared setting, a utility calculation. That's what static is for.
Every student has their own student number (object property). But the school's noticeboard is shared โ there's exactly one, and everyone reads the same board. A static property is that noticeboard: it belongs to the class itself, not to any single object. Change it, and everyone sees the change.
Static properties โ one shared value
<?php
class Student {
public static int $count = 0; // the shared noticeboard
public function __construct(public string $name) {
self::$count++; // every new student updates the shared counter
}
}
new Student("Chanda");
new Student("Mutinta");
new Student("Bwalya");
echo "Students registered: " . Student::$count;
Two brand-new symbols:
::โ the double colon (officially the "scope resolution operator"). It accesses things on a class, the way->accesses things on an object.Student::$count= "the Student class's count".self::โ used inside a class to refer to the class itself, the way$thisrefers to the current object.self::$count= "my class's count".
With objects: $this->name (no $ after the arrow).
With statics it's the opposite: self::$count โ the $ stays.
Mixing these up is the number-one static syntax error.
Static methods โ skills that need no object
A static method belongs to the class and is called without creating any object. Perfect for utility work that doesn't depend on any particular object's data:
class Fees {
public static function withVat(float $amount): float {
return round($amount * 1.16, 2);
}
public static function format(float $amount): string {
return "K" . number_format($amount, 2);
}
}
// No "new" anywhere โ call directly on the class:
echo Fees::format(Fees::withVat(5000));
Inside a static method there is no $this. Think about it: the
method runs without any object existing โ so "me, myself" points at nobody. If a method needs
$this, it cannot be static. If it never touches $this, it's a
candidate for static.
Class constants โ values carved in stone
Constants are values that never change โ no $, written in
CAPITALS by convention, accessed with :::
class Grade {
const PASS_MARK = 50;
const DISTINCTION = 75;
public static function of(int $marks): string {
if ($marks >= self::DISTINCTION) return "Distinction";
if ($marks >= self::PASS_MARK) return "Pass";
return "Fail";
}
}
echo "Pass mark is " . Grade::PASS_MARK . "<br>";
echo "67 => " . Grade::of(67);
Why constants instead of plain numbers scattered in the code? Because
Grade::PASS_MARK explains itself, lives in exactly one place, and if the university
senate changes the pass mark to 45, you edit one line and the whole system
follows. Numbers sprinkled through code ("magic numbers") are a maintenance nightmare.
A realistic combined example
class StudentNumber {
const PREFIX = "LGU";
private static int $lastSerial = 0;
public static function generate(int $year): string {
self::$lastSerial++;
// str_pad turns 7 into "007"
return self::PREFIX . $year . "-" . str_pad(self::$lastSerial, 3, "0", STR_PAD_LEFT);
}
}
echo StudentNumber::generate(2026) . "<br>";
echo StudentNumber::generate(2026) . "<br>";
echo StudentNumber::generate(2026);
A shared constant, a shared private counter, a public static generator โ no objects needed. This is exactly how real systems mint sequential IDs, invoice numbers and receipt numbers.
When to use static โ and when not to
- โ Counters and shared state that genuinely belongs to the whole class.
- โ Pure utility/helper calculations (formatting, converting, validating).
- โ Constants for fixed configuration values.
- โ Don't make everything static "because it's easier" โ you lose the entire benefit of objects (separate data, polymorphism, testability). If in doubt, prefer normal objects.
Build a class Converter with a constant KWACHA_PER_DOLLAR = 27.5 and
two static methods: toKwacha(float $usd) and toDollars(float $zmw).
Convert $100 to Kwacha and K550 to dollars, printing both.
Show solution
<?php
class Converter {
const KWACHA_PER_DOLLAR = 27.5;
public static function toKwacha(float $usd): float {
return round($usd * self::KWACHA_PER_DOLLAR, 2);
}
public static function toDollars(float $zmw): float {
return round($zmw / self::KWACHA_PER_DOLLAR, 2);
}
}
echo "$100 = K" . Converter::toKwacha(100) . "<br>";
echo "K550 = $" . Converter::toDollars(550);
How do you access a static property from outside the class?
Why can't a static method use $this?
staticmembers belong to the class (one shared noticeboard), not to objects.- Access with
::โ from outside:Student::$count; from inside:self::$count. - Static methods are called without
newand can never use$this. const NAME = value;defines unchangeable class constants โ CAPITALS, no$.- Constants kill "magic numbers": one named value, one place to change it.
- Use static for shared counters, utilities and config โ not as a lazy way to avoid objects.