Classes and Objects

Object-oriented programming bundles data and the code that works on it into objects. A class is the blueprint: it declares the properties each object has and the methods it can perform. Every modern PHP framework and library is built from classes, so this is where PHP code starts to look professional.

Defining a class

PHP
<?php

class Dog
{
    public string $name = "";
    public int $age = 0;

    public function bark(): string
    {
        return "{$this->name} says woof!";
    }

    public function birthday(): void
    {
        $this->age++;
    }
}

$dog = new Dog();
$dog->name = "Biscuit";
$dog->age = 3;

echo $dog->bark(), "\n";
$dog->birthday();
echo "{$dog->name} is now {$dog->age}\n";
Output
Biscuit says woof!
Biscuit is now 4
  • class Dog { … } declares the class. Class names are PascalCase.
  • Properties ($name, $age) hold each object's data. Give them types and default values.
  • Methods are functions inside the class.
  • new Dog() creates an instance. -> accesses its properties and methods.
  • Inside a method, $this refers to the object the method was called on.

Note that properties are written without the dollar sign after the arrow: $dog->name, not $dog->$name.

Making properties public so outside code can change them freely is fine for a first example; the next lessons show how constructors, visibility and readonly properties keep objects valid.

Each object has its own data

PHP
<?php

class Counter
{
    public int $value = 0;

    public function increment(): static
    {
        $this->value++;
        return $this;       // returning $this allows chaining
    }
}

$a = new Counter();
$b = new Counter();

$a->increment()->increment()->increment();
$b->increment();

echo "a = {$a->value}, b = {$b->value}\n";
Output
a = 3, b = 1

A method that returns $this enables method chaining, a style used by many libraries (query builders, for example).

Objects are passed by handle

Arrays are copied when assigned or passed to functions, but objects aren't: the variable holds a handle to the object, and copying it gives another handle to the same object. A function can therefore change an object it receives:

PHP
<?php

class Account
{
    public float $balance = 0;
}

function deposit(Account $account, float $amount): void
{
    $account->balance += $amount;
}

$mine = new Account();
$alias = $mine;

deposit($mine, 100);
$alias->balance += 50;

echo $mine->balance, "\n";
var_dump($mine === $alias);
Output
150
bool(true)

To get an independent copy, use clone:

PHP
<?php

class Point
{
    public int $x = 0;
    public int $y = 0;
}

$p1 = new Point();
$p2 = clone $p1;
$p2->x = 10;

echo "{$p1->x} {$p2->x}\n";
var_dump($p1 == $p2, $p1 === $p2);
Output
0 10
bool(false)
bool(false)

== compares objects property by property; === checks whether two variables refer to the same object.

Undefined properties

Reading a property that isn't declared gives a warning, and creating one on the fly is deprecated (it will become an error) — another reason to declare every property:

PHP
<?php

class User
{
    public string $name = "Ana";
}

$u = new User();
echo $u->email ?? "(no email)", "\n";
$u->nickname = "ana99";
Output
(no email)

Deprecated: Creation of dynamic property User::$nickname is deprecated in main.php on line 10

Inspecting objects

PHP
<?php

class Book
{
    public string $title = "Dune";
    public int $pages = 412;
}

$book = new Book();
var_dump($book);
echo get_class($book), "\n";
var_dump($book instanceof Book);
print_r(get_object_vars($book));
Output
object(Book)#1 (2) {
  ["title"]=>
  string(4) "Dune"
  ["pages"]=>
  int(412)
}
Book
bool(true)
Array
(
    [title] => Dune
    [pages] => 412
)

Methods that use other objects

PHP
<?php

class Point
{
    public float $x = 0;
    public float $y = 0;

    public function distanceTo(Point $other): float
    {
        return sqrt(($other->x - $this->x) ** 2 + ($other->y - $this->y) ** 2);
    }
}

$home = new Point();
$shop = new Point();
$shop->x = 3;
$shop->y = 4;

echo $home->distanceTo($shop), "\n";
Output
5

Thinking in objects

When designing classes, look for the nouns in a problem — customer, order, invoice, product — as candidate classes, and the verbs — place, cancel, total, ship — as their methods. A good class has one clear responsibility and keeps its data together with the code that changes it.

Try it yourself

Complete a Rectangle class with area, perimeter and isSquare methods.

Try it yourself · main.php
Edit the code, copy it into main.php, then run it with php main.php (PHP 8.5). How to install PHP
Output
Area: 10, perimeter: 13
Square? no