13. Objects

With the release of PHP 5, support for Object-Oriented Programming (OOP) was added. Before continuing I want you to know that there are 3 paradigms or ways to organize your code:

  • Structured: Just as we have worked so far. The instructions follow an order from the beginning of the file to the end.
  • Functional: functions that call other functions (declared or anonymous). Its potential lies in the fact that many errors are avoided. There are better languages than PHP for this purpose (Lisp, Elixir, Haskell...).
  • Objects: Encapsulate variables and functions.

Objects allow us to keep in one place a large number of variables and functions that can be merged with other places. Don't worry, I'm not looking for you to handle them like an expert, but for you to be able to interpret and create simple objects.

Class

In the example we have an object that we have called Gato. Inside it contains a variable and a function.

// Declaration
class Gato
{
    // Public variables
    public $nombre = 'Felix';

    /**
     * Method to hear the cat
     * @return void
     */
    public function maullar(): void
    {
        echo 'Miiiiauuuu';
    }
}

To use it you must instantiate it. For that there is a reserved word called new.

// The Gato object is instantiated
$miGato = new Gato();

Now you can use its interior with the arrows ->.

// The Gato function is called
$miGato->maullar();
// echo: Miiiiauuuu
echo $miGato->nombre;
// echo: Felix

Constructor

Constructors are the functions that will be executed when the object is created.

For example.

// Declaration
class Gato
{
    // Public variables
    public $nombre = 'Felix';

    /**
     * Method to hear the cat
     * @return void
     */
    function __construct()
    {
        echo 'Miiiiauuuu';
    }
}

new Gato();
// Miiiiauuuu

One of its most widespread uses is to define its values when creating the object.

// Declaration
class Gato
{
    // Public variables
    public string $nombre = '';

    /**
     * @return void
     */
    function __construct(string $nombre)
    {
        $this->nombre = $nombre;
    }
}

$miGato = new Gato('Federico');
echo $miGato->nombre;
// Federico

It can be summarized with the following structure.

// Declaration
class Gato
{
    /**
     * @return void
     */
    function __construct(public string $nombre = '')
    {
        // Nothing to do, take a break
    }
}

$miGato = new Gato('Gustavo');
echo $miGato->nombre;
// Gustavo

Constructor Property Promotion (PHP 8.0+): This compact syntax is called "constructor property promotion". It allows you to declare and assign properties directly in the constructor signature, saving repetitive code. It is especially useful when you have many properties that you only need to initialize.

We can also have several constructors that perform different functions.

// Declaration
class Gato
{
    // Public variables
    public string $nombre = 'Felix';

    /**
     * Method to hear the cat
     * @return void
     */
    function __construct(...$args)
    {
        if (isset($args[0])) {
            $this->nombre = $args[0];
            echo 'Hola ' . $this->nombre;
        } else {
            echo 'Miiiiauuuu';
        }
    }
}

$miGatoFavorito = new Gato();
// Miiiiauuuu
echo $miGatoFavorito->nombre;
// Felix

$miGatoTalVezVivo = new Gato('Schrodinger');
// Hola Schrodinger
echo $miGatoFavorito->nombre;
// Schrodinger

Read-only properties (PHP 8.1+)

readonly properties can be initialized only once and cannot be modified afterwards. They are perfect for values that must not change after the object is constructed.

class Usuario
{
    public function __construct(
        public readonly string $id,
        public readonly string $email,
        public string $nombre
    ) {}
}

$usuario = new Usuario('123', 'usuario@ejemplo.com', 'Ana');
echo $usuario->id;
// 123

// This is allowed
$usuario->nombre = 'María';

// This will throw an error
$usuario->id = '456';
// Error: Cannot modify readonly property Usuario::$id

Advantages of readonly: - Greater security, avoids accidental modifications. - Clearer code by indicating which values are immutable. - Useful for DTOs (Data Transfer Objects) and Value Objects.

Enumerations (PHP 8.1+)

Enumerations (Enums) allow you to define a type with a fixed set of possible values. They are ideal for representing states, roles, categories or any value that has limited options.

// Basic enum (backed by strings)
enum Estado: string
{
    case PENDIENTE = 'pendiente';
    case APROBADO = 'aprobado';
    case RECHAZADO = 'rechazado';
}

// Usage
function procesarPedido(Estado $estado): void
{
    echo match($estado) {
        Estado::PENDIENTE => 'The order is pending review',
        Estado::APROBADO => 'The order has been approved',
        Estado::RECHAZADO => 'The order has been rejected',
    };
}

procesarPedido(Estado::APROBADO);
// The order has been approved
// Enum with methods
enum Rol: string
{
    case ADMIN = 'admin';
    case EDITOR = 'editor';
    case VIEWER = 'viewer';

    public function puedeEditar(): bool
    {
        return match($this) {
            self::ADMIN, self::EDITOR => true,
            self::VIEWER => false,
        };
    }

    public function descripcion(): string
    {
        return match($this) {
            self::ADMIN => 'Administrator with all permissions',
            self::EDITOR => 'Can edit content',
            self::VIEWER => 'Can only view content',
        };
    }
}

$rol = Rol::EDITOR;
echo $rol->descripcion();
// Can edit content
var_dump($rol->puedeEditar());
// bool(true)

Advantages of Enums: - Safer and self-documented code. - Prevents invalid values. - The IDE can autocomplete the possible values. - Allows associating methods and behaviors with the values.

Visibility

One of the most important features of objects is visibility, or the permissions that variables or functions can have. Similar to granting access privileges.

The possibilities are:

  • public: anyone can use it.
  • private: only accessible from the object itself.
  • protected: only accessible from the object itself or its heirs.

If not indicated otherwise, it will be public.

/**
 * Definition of Amigo
 */
class Amigo
{
    // Declaration of a public constructor
    public function __construct() { }

    // Declaration of a public method
    public function MyPublic() { }

    // Declaration of a protected method
    protected function MyProtected() { }

    // Declaration of a private method
    private function MyPrivate() { }

    // This is public
    function tomarCerveza()
    {
        $this->MyPublic();
        $this->MyProtected();
        $this->MyPrivate();
    }
}

Inheritance

It is possible to instantiate an object and merge the variables and functions of another already instantiated object. For this we use the reserved word extends.

// Inherits everything from the Gato object
class Garfield extends Gato {

    // Public variables
    public $nombre = 'Garfield';

    /**
     * Method to express the favorite food
     * @return void
     */
    public function comidaFavorita(): void
    {
        echo 'Lasaña';
    }
}

We instantiate our cat Garfield.

// The Garfield object is instantiated
$miGatoComilon = new Garfield();

And now we can use all the variables and functions of both Gato and Garfield. But... what happens with the variable that has the same name ($nombre)? Since Garfield is the child, it overwrites it with its value.

// The Gato function is called
$miGatoComilon->maullar();
// echo: Miiiiauuuu
// The Garfield function is called
$miGatoComilon->comidaFavorita();
// echo: Lasaña
echo $miGatoComilon->nombre;
// echo: Garfield

Many concepts are left along the way that we won't cover.

  • Overloading.
  • Statics.
  • Interfaces.
  • Abstraction.
  • Traits.
  • ...

For now we will leave it here, there is no need to go much deeper as long as we know how to use them.

Activity 1

Create an object called Cuenta for a bank with the following needs.

  • Variables: name, surnames, ID number, balance and active.
  • Functions: update customer data, deposit money, subtract money, block, unblock, show customer information.

Try all the possibilities.

Activity 2

Create an object called Habitación for a hotel chain with the following needs.

  • Variables: number, beds, available, clean and capacity.
  • Functions: update room data, mark as dirty, mark as clean, mark as available, mark as occupied, view capacity and view number.

Try all the possibilities.

This work is under a Attribution-NonCommercial-NoDerivatives 4.0 International license.

Desafíos de programación atemporales y multiparadigmáticos

Desafíos de programación atemporales y multiparadigmáticos

Te encuentras ante un librillo de actividades, divididas en 2 niveles de dificultad. Te enfrentarás a los casos más comunes que te puedes encontrar en pruebas técnicas o aprender conceptos elementales de programación.

Buy the book

Will you buy me a coffee?

This is how I keep writing without ads or paywalls.

Comments

There are no comments yet.