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:


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

📝 Exercises

  1. Create a Book class with properties title/author/price, a constructor to initialize them, and a getInfo() method that returns book information.
  2. Create a BankAccount class 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.
  3. Rewrite exercise 1 using PHP 8 constructor property promotion. See how many lines of code you save.
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏