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.
readonlyfor 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.
Product class
Create a
Produitclass using constructor promotion:nom(string),prixHt(float),stock(int, default 0), all public. Add:prixTtc(float $taux = 0.2): floatrounded to 2 decimals;estDisponible(): bool(stock strictly positive).
declare(strict_types=1); class Produit { // à compléter }Immutable amount
Create a
finalclassMontantwith apublic readonly int $centimesproperty (the amount in cents avoids float rounding errors). Add:ajouter(Montant $autre): Montantthat returns a new object;format(): stringthat returns, for example,"12,50 €"for 1250 cents.
declare(strict_types=1); final class Montant { // à compléter }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
Which keyword creates an instance of a class?
- class
- new
- create
What does constructor promotion allow?
- Inheriting from another class
- Declaring and initializing properties directly in the constructor parameters
- Making the constructor static
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
- Encapsulation and Inheritance18 min
- Interfaces, Polymorphism and Traits18 min
- Static Members, Constants and Enumerations16 min
- Handling Errors with Exceptions16 min
- Namespaces, Composer and PSR-4 Autoloading20 min