PHP: Classes and Objects
You've written 21 lessons of procedural code, and you're probably starting to feel that things get messy as your codebase grows. Object-oriented programming (OOP) solves this problem—it bundles related data and functions into "classes," making code more organized and reusable.
1. Why Do We Need Classes and Objects?
Think of it with a real-world analogy:
TEXT
📖 Display only
Procedural: You follow a checklist every time you bake a cake — crack eggs → add flour → mix → bake
Object-oriented: You have a "cake machine" (class). Press "make" and out comes a cake (object)
Let's compare code:
PHP
<?php
// Procedural: data and functions are scattered
$userName = "John";
$userAge = 25;
function greet($name) {
return "Hello, {$name}";
}
echo greet($userName);
// Object-oriented: data and functions are bundled together
class User {
public string $name;
public int $age;
function greet(): string {
return "Hello, {$this->name}";
}
}
$user = new User();
$user->name = "John";
$user->age = 25;
echo $user->greet();
?>
💡 Tip: OOP isn't a "better" way to program—it's a tool for organizing complex code. Small scripts are simpler with procedural code. The advantages of OOP become clear once your codebase exceeds 500 lines.
2. Defining a Class
PHP
<?php
class Car {
// Properties (data)
public string $brand;
public string $color;
public int $year;
// Methods (behavior)
public function start(): string {
return "{$this->brand} is starting!";
}
public function honk(): string {
return "Beep beep!";
}
}
?>
Key syntax points:
- Use the
classkeyword to define a class. Class names usePascalCase. - Declare properties with
public string $name;(PHP 7.4+ supports type declarations). $thisrefers to the current object inside a method.
3. Creating Objects
A class is just a "blueprint." You create concrete "objects" with the new keyword:
PHP
<?php
// From one blueprint (class), create three specific cars (objects)
$car1 = new Car();
$car1->brand = "Toyota";
$car1->color = "White";
$car1->year = 2024;
$car2 = new Car();
$car2->brand = "BMW";
$car2->color = "Black";
$car2->year = 2023;
echo $car1->start(); // Toyota is starting!
echo $car2->start(); // BMW is starting!
// Use the arrow operator -> to access properties and methods
echo $car1->brand; // Toyota
$car1->color = "Red"; // Modify a property
echo $car1->color; // Red
?>
4. The __construct Method
The constructor is called automatically when you use new, letting you initialize an object:
PHP
<?php
class Car {
public string $brand;
public string $color;
public int $year;
// Constructor
public function __construct(string $brand, string $color, int $year) {
$this->brand = $brand;
$this->color = $color;
$this->year = $year;
}
public function getInfo(): string {
return "{$this->year} {$this->color} {$this->brand}";
}
}
// Pass arguments when creating the object
$car = new Car("Toyota", "White", 2024);
echo $car->getInfo(); // 2024 White Toyota
?>
💡 Tip: In
$this->brand = $brand, the left side $this->brand is the property and the right side $brand is the parameter. PHP 8.0+ supports constructor property promotion, which makes this even cleaner—see below.
▶ Example: PHP 8 Constructor Property Promotion
Output:
TEXT
📖 Display only
value
PHP
<?php
// PHP 8.0+ simplified syntax
class Car {
public function __construct(
public string $brand,
public string $color,
public int $year,
) {
// Parameters automatically become properties! No more $this->brand = $brand
}
}
$car = new Car("Toyota", "White", 2024);
echo $car->brand; // Toyota ✅
?>
Output:
TEXT
📖 Display only
Output displayed
💡 Tip: This is one of PHP 8's biggest improvements—constructor property promotion cuts boilerplate in half. New projects should use this syntax.
5. Access Modifiers
Access modifiers control the visibility of properties and methods:
PHP
<?php
class BankAccount {
public string $bank = "Bank of China"; // Anyone can see and modify
private float $balance = 0; // Only accessible inside the class
protected string $accountId; // Accessible inside the class and subclasses
public function __construct(
private string $owner,
private float $initialDeposit = 0.0
) {
$this->balance = $initialDeposit;
}
// Safely manipulate private properties through public methods
public function deposit(float $amount): void {
if ($amount > 0) {
$this->balance += $amount;
}
}
public function getBalance(): float {
return $this->balance;
}
}
$account = new BankAccount("John", 1000);
echo $account->bank; // Bank of China ✅ public is accessible
$account->deposit(500); // ✅ public method can be called
echo $account->getBalance(); // 1500 ✅
// echo $account->balance; // ❌ Error: private property not directly accessible
// $account->balance = 9999; // ❌ Error: can't arbitrarily change the balance
?>
| Modifier | Alias | Access Scope |
|---|---|---|
public |
Public | Accessible everywhere |
protected |
Protected | Current class and subclasses |
private |
Private | Current class only |
💡 Tip: Make properties
private or protected and access them through public methods—this is called encapsulation. It lets you control how data is modified, for example, deposit() can include validation.
6. Comparing Objects
PHP
<?php
class User {
public function __construct(
public string $name,
public int $age
) {}
}
$u1 = new User("John", 25);
$u2 = new User("John", 25);
$u3 = $u1;
var_dump($u1 == $u2); // true (same property values)
var_dump($u1 === $u2); // false (not the same object)
var_dump($u1 === $u3); // true (pointing to the same object)
?>
7. Complete Example: A User Class
▶ Example: A Complete User Class
Output:
TEXT
📖 Display only
root
User status: " . root->getDisplayName() . "<br>
Password correct!
PHP
<?php
class User {
private string $passwordHash; // Password hash—never exposed
public function __construct(
public string $username,
public string $email,
string $password, // Regular parameter (not a property)
public int $age = 0,
public bool $isActive = true,
) {
// Password is hashed during construction
$this->passwordHash = password_hash($password, PASSWORD_DEFAULT);
}
public function verifyPassword(string $password): bool {
return password_verify($password, $this->passwordHash);
}
public function getDisplayName(): string {
return $this->username . ($this->isActive ? '' : ' (Deactivated)');
}
public function greet(): string {
return "Hello, {$this->username}! Your email is {$this->email}.";
}
}
// Usage
$user = new User("John", "john@example.com", "secret123", 25);
echo $user->greet();
echo "User status: " . $user->getDisplayName() . "<br>";
if ($user->verifyPassword("secret123")) {
echo "Password correct!";
}
// echo $user->passwordHash; // ❌ Error: private, not accessible
?>
Output:
TEXT
📖 Display only
Hello, John! Your email is john@example.com.
User status: John
Password correct!
▶ Example: Calculator Class with Encapsulated Logic
Output:
TEXT
📖 Display only
result
PHP
<?php
class Calculator {
private float $result = 0;
public function add(float $n): self {
$this->result += $n;
return $this;
}
public function subtract(float $n): self {
$this->result -= $n;
return $this;
}
public function getResult(): float {
return $this->result;
}
}
$calc = new Calculator();
echo $calc->add(10)->subtract(3)->add(5)->getResult(); // 12
?>
Output:
TEXT
📖 Display only
Output displayed
❓ FAQ
Q When should I use a class vs. a function?
A Use a class when data and the functions that operate on it naturally belong together. For example, a "user" has name/age/email properties and login/logout methods. If you just have a few unrelated utility functions, plain functions are fine.
Q What is
$this?A
$this is a reference to "the current object being operated on" inside an object method. For instance, inside $car1->start(), $this refers to $car1.Q Why not use
var to declare properties?A That's PHP 4 syntax and it's obsolete. Modern PHP always uses
public/private/protected with type declarations.📖 Summary
classdefines a blueprint,newcreates an object$thisrefers to the current object inside a method__construct()runs automatically onnew, initializing the object- PHP 8 constructor property promotion: write
public string $namedirectly in parameters public/private/protectedcontrol visibility- Encapsulation: private properties + public methods, controlling how data is modified
📝 Exercises
- Create a
Bookclass with properties title/author/price, a constructor to initialize them, and agetInfo()method that returns book information. - Create a
BankAccountclass with a private balance, public deposit and withdraw methods (withdrawals can't exceed the balance), and a public method to check the balance. Create a few accounts and test operations. - Rewrite exercise 1 using PHP 8 constructor property promotion. See how many lines of code you save.