In questo articolo “Il paradigma ad oggetti in PHP” vediamo come sia possibile implementare il paradigma ad oggetti in PHP . Al termine dell’articolo vediamo anche esempi pratici

In questo articolo “Il paradigma ad oggetti in PHP” vediamo come sia possibile implementare il paradigma ad oggetti in PHP . Al termine dell’articolo vediamo anche esempi pratici


main.zip (101 download )

Indice dei contenuti

PHP implementa il paradigma degli oggetti (Object-Oriented Paradigm) a partire dalla versione 5.0. Questo paradigma permette di strutturare il codice in classi e oggetti, migliorando l’organizzazione e la riusabilità del codice.

Creazione di una classe in PHP

Per creare una nuova classe, si utilizza il costrutto class, all’interno del quale vengono definite proprietà (variabili) e metodi (funzioni). Le proprietà devono essere dichiarate con uno dei modificatori di visibilità: public, private o protected.

Ecco la sintassi di base per la dichiarazione di una classe in PHP:

class NomeClasse {
    // Proprietà della classe
    public $proprieta1;
    private $proprieta2;

    // Metodo costruttore
    public function __construct($valore) {
        $this->proprieta1 = $valore;
    }

    // Metodo pubblico
    public function metodoEsempio() {
        return "Valore: " . $this->proprieta1;
    }
}

Esempio: Classe Carrello

Creiamo ora una classe Carrello, che rappresenta un carrello della spesa. La classe avrà due proprietà:

  • $articoli: un array che memorizza gli articoli presenti nel carrello.
  • $quantita: un array associativo che tiene traccia della quantità di ogni articolo.

La classe includerà metodi per:

  • Aggiungere un articolo al carrello.
  • Rimuovere un articolo.
  • Visualizzare il contenuto del carrello.

Ecco il codice della classe con i commenti esplicativi:

<?php
class Carrello {
    // Proprietà per memorizzare gli articoli e la quantità
    private $articoli = [];
    private $quantita = [];

    // Metodo per aggiungere un articolo al carrello
    public function aggiungiArticolo($nomeArticolo, $quantita) {
        // Se l'articolo esiste già, aggiorniamo la quantità
        if (isset($this->quantita[$nomeArticolo])) {
            $this->quantita[$nomeArticolo] += $quantita;
        } else {
            // Altrimenti, aggiungiamo l'articolo e la quantità
            $this->articoli[] = $nomeArticolo;
            $this->quantita[$nomeArticolo] = $quantita;
        }
    }

    // Metodo per rimuovere un articolo dal carrello
    public function rimuoviArticolo($nomeArticolo) {
        if (isset($this->quantita[$nomeArticolo])) {
            unset($this->quantita[$nomeArticolo]);
            $this->articoli = array_diff($this->articoli, [$nomeArticolo]);
        }
    }

    // Metodo per visualizzare il contenuto del carrello
    public function mostraCarrello() {
        echo "Contenuto del carrello:\n";
        foreach ($this->quantita as $articolo => $qta) {
            echo "- $articolo: $qta\n";
        }
    }
}

// Esempio di utilizzo della classe
$carrello = new Carrello();
$carrello->aggiungiArticolo("Mela", 3);
$carrello->aggiungiArticolo("Pane", 2);
$carrello->aggiungiArticolo("Mela", 1); // Aggiunge altre 1 mela
$carrello->rimuoviArticolo("Pane");
$carrello->mostraCarrello(); //ho aggiunto 3 mele, 2 pane, 1 mela e ho rimosso 2 pane quindi visualizzerò: 4 mele

?>

Spiegazione del codice

In PHP, this è una parola chiave utilizzata all’interno di una classe per fare riferimento all’istanza corrente dell’oggetto.

Quando creiamo un oggetto da una classe, possiamo usare $this per accedere alle sue proprietà e metodi all’interno della classe stessa.

Dentro il costruttore :

  • $this->nome = $nome; → assegna il valore ricevuto al campo $nome dell’oggetto attuale.

In un metodo:

  • $this->nome;$this->nome fa riferimento al nome dell’oggetto su cui il metodo è stato chiamato.

Nell’esempio nella riga:

if (isset($this->quantita[$nomeArticolo])) {

La funzione isset() controlla se la chiave $nomeArticolo esiste all’interno dell’array $this->quantita.

$this->quantita è un array associativo, dove la chiave è il nome dell’articolo e il valore è la quantità.

Se la chiave esiste, significa che l’articolo è già presente nel carrello.

Se l’articolo è già nel carrello, aggiorniamo la quantità:

$this->quantita[$nomeArticolo] += $quantita;

Se l’articolo è già presente, invece di sovrascrivere il valore, lo incrementiamo aggiungendo la nuova quantità specificata come argomento del metodo.

Ad esempio, se il carrello contiene già 2 mele ("Mela" => 2) e aggiungiamo altre 3 mele, il valore diventa "Mela" => 5.

Se l’articolo non è presente, lo aggiungiamo:

} else {
    $this->articoli[] = $nomeArticolo;
    $this->quantita[$nomeArticolo] = $quantita;
}

Se la chiave non esiste, significa che l’articolo non è ancora nel carrello.

Aggiungiamo quindi il nome dell’articolo all’array $this->articoli[] per tenerne traccia.

Creiamo una nuova chiave in $this->quantita e le assegniamo la quantità ricevuta.

Nella funzione rimuoviArticolo, La funzione unset() elimina la chiave corrispondente a $nomeArticolo dall’array $this->quantita.

Dopo questa operazione, l’articolo non avrà più una quantità associata.

  • array_diff() confronta due array e rimuove gli elementi del secondo array dal primo.
  • $this->articoli è l’elenco degli articoli nel carrello (senza le quantità).
  • [$nomeArticolo] è un array che contiene solo l’articolo da eliminare.

Esempio prima dell’operazione Se $this->articoli contiene:

["Mela", "Pane"]

e chiamiamo rimuoviArticolo("Mela"), l’operazione:

$this->articoli = array_diff($this->articoli, ["Mela"]);

restituirà:

["Pane"]

La riga di codice nella funzione mostraCarrello:

foreach ($this->quantita as $articolo => $qta)

a parte di un ciclo foreach, che viene utilizzato per iterare su ogni elemento di un array associativo. In questo caso, l’array è $this->quantita, che è un array associativo in cui le chiavi sono i nomi degli articoli e i valori sono le quantità degli articoli nel carrello.

Vediamo come funziona dettagliatamente:

Cosa fa foreach?

Il costrutto foreach è un ciclo che scorre tutti gli elementi di un array. Per ogni iterazione, restituisce una chiave (in questo caso $articolo, cioè il nome dell’articolo) e un valore (in questo caso $qta, cioè la quantità dell’articolo).

Sintassi di foreach

La sintassi del foreach in PHP è la seguente:

foreach ($array as $chiave => $valore) {
    // Codice da eseguire
}
  • $array è l’array su cui iteriamo (in questo caso, $this->quantita).
  • $chiave è la chiave dell’elemento dell’array (in questo caso, il nome dell’articolo, come “Mela” o “Pane”).
  • $valore è il valore associato alla chiave nell’array (in questo caso, la quantità, come 3 per “Mela” o 2 per “Pane”).

Esempio pratico

Supponiamo che l’array $this->quantita contenga:

$this->quantita = [
    "Mela" => 3,
    "Pane" => 2,
    "Latte" => 1
];

Quando usiamo il ciclo foreach, PHP itera su ogni elemento dell’array $this->quantita. Alla prima iterazione, la variabile $articolo sarà "Mela" e la variabile $qta sarà 3. Alla seconda iterazione, $articolo sarà "Pane" e $qta sarà 2, e così via.

Esecuzione del codice

foreach ($this->quantita as $articolo => $qta) {
    echo "$articolo: $qta\n";
}

Il ciclo stampa, riga per riga:

Mela: 3
Pane: 2
Latte: 1

Perché usare foreach?

Il ciclo foreach è molto utile quando si lavora con array associativi, come in questo caso. Con foreach, possiamo facilmente accedere sia alla chiave che al valore senza dover gestire manualmente gli indici, come nel caso di un ciclo for

Costruttori deprecati

A partire da PHP 7, è stato introdotto un cambiamento significativo nella gestione dei costruttori delle classi. In precedenza, con PHP 4, i costruttori avevano la stessa denominazione della classe. Tuttavia, questa pratica ha portato a diversi problemi, in particolare quando si cambiava il nome della classe e bisognava aggiornare tutti i costruttori nei vari file.

Il problema dei costruttori in PHP 4

In PHP 4, la sintassi del costruttore era la seguente:

class Carrello {
    function Carrello() {
        // codice per inizializzare l'oggetto
    }
}

Il costruttore aveva lo stesso nome della classe (in questo caso, Carrello), ma questo approccio presentava diversi svantaggi:

  • Se cambiavi il nome della classe, dovevi modificare anche il nome del costruttore in tutti i file.
  • La sintassi risultava poco chiara in alcuni casi, specialmente in scenari di eredità o quando venivano utilizzate classi in framework complessi.

Sintassi deprecata con PHP 7

A partire da PHP 7, questa sintassi è stata deprecata. L’uso di un costruttore con lo stesso nome della classe porta alla visualizzazione di messaggi di avviso e errori. Questo può rappresentare un problema quando si aggiorna il codice, poiché il vecchio formato potrebbe causare una degradazione delle prestazioni e una gestione meno efficiente del codice.

La nuova sintassi del costruttore: __construct()

Per risolvere questo problema, PHP 5 ha introdotto il costruttore generico __construct(). In questo modo, il costruttore non è più legato al nome della classe, ma a una funzione predefinita che consente di evitare conflitti e migliorare la leggibilità del codice.

La nuova sintassi, introdotta già in PHP 5 e divenuta obbligatoria con PHP 7, prevede l’uso del metodo __construct().

Esempio con la nuova sintassi:

<?php
class Carrello {
    private $articoli = [];

    // Costruttore con la sintassi nuova
    public function __construct() {
        $this->articoli = [];
        echo "Carrello creato!";
    }

    public function aggiungiArticolo($articolo) {
        $this->articoli[] = $articolo;
    }

    public function mostraArticoli() {
        foreach ($this->articoli as $articolo) {
            echo $articolo . "<br>";
        }
    }
}

// Creazione di un oggetto Carrello
$carrello = new Carrello();  // Chiamata al costruttore __construct
$carrello->aggiungiArticolo("Mela");
$carrello->aggiungiArticolo("Pane");
$carrello->mostraArticoli();
?>

Perché usare __construct()?

  1. Compatibilità con le versioni future: PHP 7 ha dichiarato deprecato l’uso del costruttore con il nome della classe e PHP 8 rimuoverà completamente questa funzionalità. Utilizzare __construct() è quindi essenziale per garantire la compatibilità futura del codice.
  2. Chiarezza e manutenzione del codice: Poiché il costruttore è sempre definito come __construct(), non dipende più dal nome della classe. Ciò significa che se il nome della classe cambia, non è necessario modificare il nome del costruttore, rendendo il codice più facile da gestire e meno soggetto a errori.
  3. Ereditarietà: Se la classe viene estesa (ovvero se una classe eredita un’altra classe), il costruttore __construct() consente di richiamare facilmente i costruttori delle classi genitore tramite parent::__construct(), senza necessità di modificare ogni singolo costruttore delle classi derivate.

L’Ereditarietà in OOP con PHP

L’ereditarietà è uno dei concetti fondamentali della Programmazione Orientata agli Oggetti (OOP). Permette di creare una nuova classe (chiamata classe derivata o classe figlia) che eredita le proprietà e i metodi di una classe esistente (chiamata classe base o classe genitore). La classe derivata può aggiungere nuove funzionalità o modificare (override) quelle ereditate dalla classe base.

In PHP, l’ereditarietà è implementata utilizzando la parola chiave extends.


Caratteristiche dell’Ereditarietà

  1. Ereditarietà semplice: PHP supporta l’ereditarietà semplice, cioè una classe può estendere solo una classe base.
  2. Accesso ai membri: La classe derivata eredita tutte le proprietà e i metodi pubblici e protetti della classe base. Non eredita i membri privati, ma può comunque accedere ai metodi pubblici e protetti della classe base.

Sintassi dell’ereditarietà in PHP

La sintassi per estendere una classe in PHP è la seguente:

class ClasseFiglia extends ClasseBase {
    // Nuovi metodi e proprietà
}

Nel caso dell’ereditarietà, la classe figlia può utilizzare tutto ciò che è presente nella classe base, aggiungendo nuove funzionalità o modificando quelle esistenti.


Esempio di Ereditarietà: Classe Carrello e Classe MioCarrello

Immagiamo di avere la nostra classe Carrello, che contiene alcune funzionalità di base per la gestione di articoli. Successivamente, desideriamo creare una classe MioCarrello, che estende Carrello e aggiunge la funzionalità per gestire un prezzo per ogni articolo nel carrello.

class MioCarrello extends Carrello {
    private $prezzo;

    // Metodo per impostare il prezzo
    public function setPrezzo($prezzo) {
        $this->prezzo = $prezzo;
    }

    // Metodo per ottenere il prezzo
    public function getPrezzo() {
        return $this->prezzo;
    }

    // Metodo per mostrare articoli e prezzo
    public function mostraArticoliConPrezzo() {
        foreach ($this->articoli as $articolo) {
            echo $articolo . " - Prezzo: " . $this->prezzo . "<br>";
        }
    }
}

Spiegazione del codice:

  1. Classe Carrello (Base):
    • Ha una proprietà protetta $articoli, che è un array che contiene gli articoli nel carrello.
    • Il metodo aggiungiArticolo($articolo) aggiunge un articolo al carrello.
    • Il metodo mostraArticoli() stampa gli articoli nel carrello.
  2. Classe MioCarrello (Derivata):
    • extends Carrello: La classe MioCarrello estende la classe Carrello. Ciò significa che eredita le proprietà e i metodi della classe Carrello.
    • $prezzo è una nuova proprietà che memorizza il prezzo degli articoli nel carrello.
    • Il metodo setPrezzo($prezzo) imposta il prezzo.
    • Il metodo getPrezzo() restituisce il prezzo.
    • Il metodo mostraArticoliConPrezzo() mostra gli articoli nel carrello insieme al prezzo.

Poichè la classe Carrello definisce $articoli come una proprietà privata, essa non può essere accessibile direttamente dalla classe derivata MioCarrello.

Quando si provia ad usare $this->articoli in MioCarrello, PHP non trova questa proprietà, e quindi restituisce un errore del tipo “Undefined property”.

Soluzione:

Per risolvere il problema, hai due opzioni:

  1. Rendere la proprietà articoli protetta (protected): In questo modo la proprietà sarà accessibile dalla classe derivata. Questo è il metodo che utilizzeremo
  2. Fornire un metodo pubblico nella classe base per accedere agli articoli.

Opzione 1: Rendere articoli protected

Si deve cambiare la visibilità della proprietà $articoli da private a protected. In questo modo, la classe MioCarrello potrà accedere direttamente a questa proprietà.

Ora vediamo un esempio di utilizzo. Dopo aver creato la classe Carrello e la classe MioCarrello che estende Carrello, creiamo due script PHP per le due classi (Carrello.php e MioCarrello.php) e creiamo lo script PHP provaCarello.php:

<?php

//richiamiamo gli script che contengono le classi carrello_new e MioCarrello
require_once("Carrello.php");
require_once("MioCarrello.php");

$carrello = new MioCarrello();
$carrello->aggiungiArticolo("Mela");
$carrello->aggiungiArticolo("Pane");

// Impostiamo il prezzo per gli articoli
$carrello->setPrezzo(2.5);

// Mostriamo gli articoli con il prezzo
$carrello->mostraArticoliConPrezzo();
?>

Output:

Mela - Prezzo: 2.5
Pane - Prezzo: 2.5

Perché usare l’Ereditarietà?

  1. Riutilizzo del codice: La classe derivata riutilizza il codice della classe base, senza doverlo riscrivere. Questo rende il codice più conciso e manutenibile.
  2. Estensione delle funzionalità: Puoi aggiungere nuove funzionalità alla classe derivata senza alterare il comportamento della classe base.
  3. Semplificazione della manutenzione: Modificare il comportamento di una classe base si riflette automaticamente su tutte le classi derivate, riducendo la necessità di aggiornamenti duplicati.

Limiti dell’Ereditarietà in PHP

  • Ereditarietà semplice: PHP supporta solo l’ereditarietà semplice, quindi una classe può estendere solo una classe base. Non è possibile ereditare da più classi contemporaneamente.
  • Ereditarietà vs Composizione: In alcuni casi, la composizione (cioè l’inclusione di oggetti di altre classi) è preferita rispetto all’ereditarietà per una maggiore flessibilità e per evitare una struttura troppo rigida.

Nella sezione DOWNLOAD o direttamente da qui: https://profgiagnotti.it/download/4860/?tmstv=1744539632 è possibile scaricare gli script descritti nell’articolo

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *