PHP · STEP 2 · OOP

PHP · OOP

PHP 8.5 (any 8.3+ works): classes, constructors, methods, inheritance and static members — the JavaScript version next to the PHP version, with constructor promotion, readonly properties, match and enums.

Step 2 of 5Laravel© Arthur Bernier Jrrewritten · verified9 code blocks289 words

What you will learn#

  • How to Create a Class
  • How to Instantiate a Class
  • Write a Constructor and Methods
  • Create an Inherited Class
  • Write Static Methods/Properties

Below you'll see JavaScript examples of object-oriented patterns and their PHP counterparts.

Creating and Instantiating a Class#

In Javascript

JS
// Creating a Classclass Dog {} // Instantiationconst Sparky = new Dog();

In PHP

PHP
<?php // Creating a classclass Dog {} // Instantiation: same new keyword$sparky = new Dog();

The Constructor and Methods#

In Javascript

JS
// Creating a Classclass Dog {  // The constructor runs when we instantiate a new instance  constructor(name, age) {    this.name = name;    this.age = age;  }   // A Method  bark() {    console.log(`${this.name} barks`);  }} // Instantiationconst Sparky = new Dog("Sparky", 4);Sparky.bark();

in PHP

PHP
<?php class Dog{    // Properties are declared up front, with a visibility and (since 7.4) a type    public string $name;    public int $age;     // The constructor runs when we instantiate a new instance    public function __construct(string $name, int $age)    {        $this->name = $name;        $this->age = $age;    }     // A method; -> reaches into the object where JavaScript uses a dot    public function bark(): void    {        echo "{$this->name} barks\n";    }} // Instantiation$sparky = new Dog("Sparky", 4);$sparky->bark();

Where JavaScript creates this.name on first assignment, PHP wants the property declared (undeclared ones are deprecated since 8.2). Because "declare, take as parameter, assign" is so repetitive, PHP 8.0 added constructor property promotion: put the visibility on the parameter — public function __construct(public string $name, public int $age) {} — and all three happen at once. The inheritance example below uses it. Add readonly (PHP 8.1) when a property must never change after construction; private and protected do what JavaScript's #private fields do.

Inheritance#

In Javascript

JS
// Creating a Classclass Dog {  // The constructor runs when we instantiate a new instance  constructor(name, age) {    this.name = name;    this.age = age;  }   // A Method  bark() {    console.log(`${this.name} barks`);  }} class SmallDog extends Dog {  constructor(name, age) {    //Super calls the constructor of the parent class    super(name, age);  }   //This will override the version of bark in the parent class  bark() {    console.log(`${this.name} yaps`);  }} // Instantiationconst Sparky = new SmallDog("Sparky", 4);Sparky.bark();

in PHP

PHP
<?php class Dog{    public function __construct(        public string $name,        public int $age,    ) {}     public function bark(): void    {        echo "{$this->name} barks\n";    }} // Same extends keywordclass SmallDog extends Dog{    public function __construct(string $name, int $age)    {        // parent:: reaches the parent class; call its constructor explicitly        parent::__construct($name, $age);    }     // This overrides the version of bark in the parent class    public function bark(): void    {        echo "{$this->name} yaps\n";    }} // Instantiation$sparky = new SmallDog("Sparky", 4);$sparky->bark();

If a child defines no __construct, the parent's runs automatically. A class extends one parent; beyond that PHP has interface (a contract to implements) and trait (methods to use).

Static Methods and Properties#

In Javascript

JS
// Static properties/methods belong to the class, not the instanceclass Calculator {  static lastResult = 0;   // a table of operator functions instead of eval()  static operations = {    "+": (a, b) => a + b,    "-": (a, b) => a - b,    "*": (a, b) => a * b,    "/": (a, b) => a / b,  };   static calculate(num1, num2, operator) {    Calculator.lastResult = Calculator.operations[operator](num1, num2);    return Calculator.lastResult;  }   static showLastResult() {    console.log(Calculator.lastResult);  }} Calculator.calculate(2, 2, "+");Calculator.showLastResult();

In PHP

PHP
<?php // Static properties/methods belong to the class, not the instanceclass Calculator{    // A property declared static is shared by the whole class    public static float $lastResult = 0.0;     // A static method: no $this inside, called on the class    public static function calculate(float $num1, float $num2, string $operator): float    {        // match instead of eval(): compares with ===, returns a value, must be exhaustive        self::$lastResult = match ($operator) {            '+' => $num1 + $num2,            '-' => $num1 - $num2,            '*' => $num1 * $num2,            '/' => $num1 / $num2,        };         return self::$lastResult;    }     public static function showLastResult(): void    {        echo self::$lastResult . "\n";    }} // Double colons access static methods/propertiesCalculator::calculate(2, 2, '+');Calculator::showLastResult(); // 4

An operator missing from the match throws UnhandledMatchError rather than silently doing nothing; add a default => arm for a fallback. When a set of named values is really a type, PHP 8.1 has an enum, and match pairs with it:

PHP
<?php enum Size{    case Small;    case Large;} $size = Size::Small;$text = match ($size) {    Size::Small => 'fits in a bag',    Size::Large => 'needs a yard',};echo $text . "\n"; // fits in a bag

Size::Small is a real type — a Size $size parameter rejects a plain string — and Laravel can cast a database column straight to it.


Resources to Learn More#


See also