Classes and Objects

First lesson of the Object-Oriented PHP and Composer course, free to read: about 15 minutes, 3 exercises and 3 quiz questions. This is the catalogue's base lesson; in the student space, it is rewritten for your profile.

Objectives

  • Declare a class with typed properties, a constructor and methods
  • Instantiate objects and call their methods with ->
  • Use constructor promotion and readonly properties

Classes and objectsConstructor and promotionReadonly properties

Why objects?

With arrays and functions, data (a product) and processing (computing its price including tax) remain separate. Object-oriented programming (OOP) groups them together: a class describes a blueprint, and each object is a concrete instance of that blueprint. This is the approach of all modern PHP frameworks (Laravel, Symfony).

A first class

<?php
declare(strict_types=1);

class Produit
{
    // Typed properties
    public string $nom;
    public float $prixHt;

    // The constructor is called automatically by new
    public function __construct(string $nom, float $prixHt)
    {
        $this->nom = $nom;        // $this = the object being built
        $this->prixHt = $prixHt;
    }

    // A method: a function that belongs to the class
    public function prixTtc(float $taux = 0.2): float
    {
        return round($this->prixHt * (1 + $taux), 2);
    }
}

$carnet = new Produit("Carnet A5", 6.5);   // instantiation
echo $carnet->nom;                          // Carnet A5
echo $carnet->prixTtc();                    // 7.8

You access properties and methods with ->. By convention, classes are named in PascalCase, with one class per file bearing the same name (Produit.php).

Constructor promotion

Since PHP 8, you can declare and initialize properties directly in the constructor signature:

<?php
class Produit
{
    public function __construct(
        public string $nom,
        public float $prixHt,
        public int $stock = 0,        // default value
    ) {}                              // empty body: everything is done

    public function estDisponible(): bool
    {
        return $this->stock > 0;
    }
}

$tasse = new Produit(nom: "Tasse", prixHt: 9.0, stock: 3); // named arguments

This is the most common form in current code.

readonly: immutable objects

A readonly property can only be assigned once, inside the class (in practice in the constructor). Any later modification throws an Error.

<?php
final class Adresse
{
    public function __construct(
        public readonly string $rue,
        public readonly string $ville,
    ) {}

    // To "modify", we return a new object
    public function avecVille(string $ville): static
    {
        return clone($this, ['ville' => $ville]);   // PHP 8.5: copy while changing ville
    }
}

$a = new Adresse("3 rue des Lilas", "Lyon");
// $a->ville = "Nantes";        // Error: Cannot modify readonly property
$b = $a->avecVille("Nantes");   // $a has not changed

Since PHP 8.5, clone($object, ['property' => value]) copies the object while replacing some properties, even readonly ones, provided it is called from within the class (as here). Before, you would write new static($this->rue, $ville). Classic pitfall: calling $a->avecVille("Nantes"); without using the result. By adding the #[\NoDiscard] attribute (PHP 8.5) above the method, PHP emits a warning when its return value is ignored. Since PHP 8.2, readonly class Adresse { ... } makes all properties readonly at once.

Objects and assignment

A variable holds a handle to the object, not a copy:

<?php
$p1 = new Produit("Stylo", 1.2);
$p2 = $p1;          // same object!
$p2->nom = "Feutre";
echo $p1->nom;      // Feutre
$p3 = clone $p1;    // real (shallow) copy

Finally, the nullsafe operator ?-> avoids errors when an object may be null: $commande?->client?->email returns null instead of crashing.

Key takeaways

  • class, new, ->, $this: the basic vocabulary.
  • Prefer constructor promotion and typed properties.
  • readonly for values that must not change after creation.

Exercises

Solutions and tests stay on the server. In the student space, your code is run and checked, and the tutor gives hints before the solution.

  1. CodeDifficulty 1Server sandbox2 hints

    Product class

    Create a Produit class using constructor promotion: nom (string), prixHt (float), stock (int, default 0), all public. Add:

    • prixTtc(float $taux = 0.2): float rounded to 2 decimals;
    • estDisponible(): bool (stock strictly positive).
    declare(strict_types=1);
    
    class Produit
    {
        // à compléter
    }
  2. CodeDifficulty 2Server sandbox2 hints

    Immutable amount

    Create a final class Montant with a public readonly int $centimes property (the amount in cents avoids float rounding errors). Add:

    • ajouter(Montant $autre): Montant that returns a new object;
    • format(): string that returns, for example, "12,50 €" for 1250 cents.
    declare(strict_types=1);
    
    final class Montant
    {
        // à compléter
    }
  3. Multiple choiceDifficulty 21 hint

    Object assignment

    After $a = new Produit("Stylo", 1.0); $b = $a; $b->nom = "Feutre";, what is the value of $a->nom?

    • "Stylo"
    • "Feutre"
    • null
    • An error

End-of-lesson quiz

  1. Which keyword creates an instance of a class?

    • class
    • new
    • create
  2. What does constructor promotion allow?

    • Inheriting from another class
    • Declaring and initializing properties directly in the constructor parameters
    • Making the constructor static
  3. What happens if you modify an already initialized readonly property?

    • The new value is ignored
    • An Error is thrown
    • The property becomes public

The rest of the course

  1. Encapsulation and Inheritance18 min
  2. Interfaces, Polymorphism and Traits18 min
  3. Static Members, Constants and Enumerations16 min
  4. Handling Errors with Exceptions16 min
  5. Namespaces, Composer and PSR-4 Autoloading20 min

Object-Oriented PHP and Composer · Intermediate · 3 h 13 min