Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Le 4 classi PHP principali del nostro e-commerce

In questo capitolo analizzeremo le quattro classi più importantio della nostra applicazione, cioè quelle che gestiscono prodotti, carrello, ordini e clienti.
In questo capitolo analizzeremo le quattro classi più importantio della nostra applicazione, cioè quelle che gestiscono prodotti, carrello, ordini e clienti.
Link copiato negli appunti

In questo capitolo vedremo in dettaglio le quattro classi principali della nostra applicazione, ossia quelle che gestiscono i prodotti, il carrello, gli ordini e i clienti e che rappresentano il flusso di lavoro dell'e-commerce.

La classe Product

Questa classe rappresenta un semplice modello di dati in cui ciascuna proprietà pubblica corrisponde al relativo campo nella tabella products.

class Product {
    public $id;
    public $name;
    public $description;
    public $price;
    public $manufacturer;
    public $image;
    public $slug;
    public function __construct($id, $name, $description, $price, $manufacturer, $image, $slug) {
        $this->id = $id;
        $this->name = $name;
        $this->description = $description;
        $this->price = $price;
        $this->manufacturer = $manufacturer;
        $this->image = $image;
        $this->slug = $slug;
    }
}

Volendo migliorare la nostra classe per il futuro prevedendo di aggiungere il salvataggio di un nuovo prodotto nel database, potremmo aggiungere un metodo che genera un ID coerente con i dati esistenti nel nostro database di esempio.

Nel caso specifico l’ID è costituito da una stringa di 10 caratteri i cui primi due caratteri sono sempre b0. Quindi possiamo scrivere:

protected function genId() {
    $prefix = 'b0';
    $output = $prefix;
    $chars = range('a','z');
    $digits = range(0, 9);
    $parts = array_merge($chars, $digits);
    for($i = 0; $i < 8; $i++) {
       $output .= $parts[mt_rand(0, count($parts) - 1)];
     }
   return $output;
}

A questo punto dovremmo modificare il costruttore verificando che l’istanza venga creata da dati esistenti o ex novo:

public function __construct($id, $name, $description, $price, $manufacturer, $image, $slug) {
        $this->id = (is_null($id)) ? $this->genId() : $id;
        $this->name = $name;
        $this->description = $description;
        $this->price = $price;
        $this->manufacturer = $manufacturer;
        $this->image = $image;
        $this->slug = $slug;
    }

Quindi per creare un prodotto che non esiste nel database useremo la seguente sintassi:

$new_product = new Product(null, 'Test', 'Lorem ipsum', 10.50, 'Acme', 'image.jpg', 'test-product');

L’ultima cosa che potremo aggiungere in futuro a questa classe è un metodo per salvare i dati nel database. Volendo potremmo inserire una chiamata al metodo save() direttamente nel costruttore in modo che l’esempio visto in precedenza salvi effettivamente i nuovi dati. Vedremo un esempio di tale metodo nelle classi successive.

La classe Cart

Questa classe è legata alla classe precedente per via del fatto che i suoi metodi per aggiungere, aggiornare e rimuovere prodotti richiedono un’istanza della classe Product.
Ha due proprietà:

  1. items: un array contenente i prodotti aggiunti con le loro quantità e il totale parziale.
  2. total: il totale del carrello senza IVA.

La maggior parte delle operazioni avviene sull’array di prodotti. Dato che questa classe va sincronizzata con la sessione, per evitare problemi il suo costruttore è definito in questo modo:

class Cart {
    private $items;
    private $total;
    public function __construct() {
        $this->items = [];
        $this->total = 0.00;
    }
}

In pratica ogni nuova istanza riparte dallo stato originario. La sincronizzazione con la sessione avviene attraverso i metodi setItems() e setTotal():

public function setItems($items) {
        $this->items = $items;
    }
public function setTotal($value) {
        $this->total = $value;
    }

Dato che le proprietà di questa classe sono private abbiamo bisogno di metodi getter per ottenerne il rispettivo valore.

public function getItems() {
    return $this->items;
}
public function getTotal() {
        return $this->total;
    }

Ora abbiamo bisogno di alcuni metodi di supporto. Il primo verifica che nel carrello ci siano effettivamente dei prodotti:

private function hasItems() {
        return ( count( $this->items ) > 0 );
    }

Il secondo impedisce che l’utente ricaricando la pagina del carrello aggiunga lo stesso prodotto al carrello modificandone quindi la quantità e il totale:

private function isInCart(Product $product) {
        if( $this->hasItems()) {
           foreach( $this->items as $item ) {
               if($item['id'] == $product->id) {
                   return true;
               }
           }
           return false;
        } else {
            return false;
        }
    }

Il terzo metodo calcola il totale del carrello sommando tutti i totali parziali dei prodotti:

private function calculateTotal() {
        $this->total = 0.00;
        if($this->hasItems()) {
            $tot = 0.00;
            foreach($this->items as $item) {
                $tot += $item['subtotal'];
            }
            $this->total = $tot;
        }
    }

Per aggiungere un prodotto al carrello prendiamo un oggetto Product e la sua quantità e aggiungiamo una entry al nostro array specificando anche la quantità e il totale parziale. Ad ogni operazione ricalcoliamo il totale.

public function addToCart(Product $product, $quantity) {
        if($quantity < 1) {
            return;
        }
        $item = [
            'id' => $product->id,
            'name' => $product->name,
            'description' => $product->description,
            'price' => $product->price,
            'manufacturer' => $product->manufacturer,
            'image' => $product->image,
            'quantity' => $quantity,
            'subtotal' => ($product->price * $quantity)
        ];
        $this->items[] = $item;
        $this->calculateTotal();
    }

Rimuovere un prodotto dal carrello si risolve in una semplice operazione di ricerca ed eliminazione di una voce da un array.

public function removeFromCart(Product $product) {
        if($this->hasItems()) {
            $i = -1;
            foreach($this->items as $item) {
                $i++;
                if($product->id == $item['id']) {
                    unset($this->items[$i]);
                    $this->calculateTotal();
                }
            }
        }
    }

L’aggiornamento del carrello con una nuova quantità per un prodotto è una speciale operazione sugli array che prevede l’uso dell’operatore di riferimento & che ci permette di modificare la voce di un array.

public function updateCart(Product $product, $quantity) {
        if($this->hasItems()) {
            foreach($this->items as &$item)  {
                if($product->id == $item['id']) {
                    $item['quantity'] = $quantity;
                    $item['subtotal'] = ($product->price * $quantity);
                    $this->calculateTotal();
                }
            }
        }
    }

La classe Customer

Questa classe ha quattro proprietà private e altrettanti metodi getter che rappresentano l’ID, il nome, il cognome e l’e-mail del cliente.

class Customer {
    private $id;
    private $firstname;
    private $lastname;
    private $email;
    public function __construct($id, $firstname, $lastname, $email) {
        $this->id = $id;
        $this->firstname = $firstname;
        $this->lastname = $lastname;
        $this->email = $email;
    }
    public function getId() {
        return $this->id;
    }
    public function getFirstName() {
        return $this->firstname;
    }
    public function getLastName() {
        return $this->lastname;
    }
    public function getEmail() {
        return $this->email;
    }
}

La vera particolarità di questa classe è in realtà il suo metodo save() che, accettando come parametro un’istanza della classe di gestione del database (che vedremo nei prossimi capitoli), salva i dati del cliente restituendo un valore bollano che indica il risultato dell’operazione:

public function save(Database $db) {
    $id = $this->id;
        $firstname = $db->escape($this->firstname);
        $lastname = $db->escape($this->lastname);
        $email = $db->escape($this->email);
        $insert = "INSERT INTO customers (id, firstname, lastname, email) VALUES ('$id', '$firstname','$lastname', '$email')";
        return $db->query($insert);
}

La classe Order

L’ordine prevede la gestione sia dei dati del carrello che di quelli del cliente. Difatti questa classe utilizza le due classi viste in precedenza. In più, questa classe aggiunge l’IVA al totale del carrello e imposta gli indirizzi di fatturazione e spedizione presi dalla pagina di checkout. Il suo costruttore ne evidenzia il funzionamento:

public function __construct($id, Cart $cart, Customer $customer) {
        $this->id = strtoupper($id);
        $this->cart = $cart;
        $this->customer = $customer;
        $this->total = $this->cart->getTotal();
        $this->status = 0;
        $this->setTotalWithTaxes();
    }

Come si può notare, la classe acquisisce i dati del cliente e del carrello rappresentati dalle rispettive classi. Il metodo invocato nel costruttore fa uso di una classe che vedremo nei prossimi capitoli e che aggiunge una tassa al totale del carrello.

public function setTotalWithTaxes() {
        if(class_exists('Vat') && defined('VAT_VALUE')) {
            $vat = new Vat(VAT_VALUE);
            $this->totalWithTaxes = $vat->add($this->total);
        } else {
            $this->totalWithTaxes = $this->total;
        }
    }

Di nuovo, la particolarità sta nel metodo con cui vengono salvati i dati nel database.

Un ordine ha anche un campo con cui possiamo memorizzare il carrello dell’ordine per riferimenti futuri. L’ordine ha anche uno status (1 o 0) che indica se il pagamento e l’elaborazione dell’ordine sono andati a buon fine.

public function save(Database $db) {
    $id = $this->id;
        $created = strftime('%Y-%m-%d %H:%M:%S', time());
        $cart = serialize($this->cart->getItems());
        $customer = $this->customer->getId();
        $billing = $db->escape($this->billing);
        $shipping = $db->escape($this->shipping);
        $total = $this->total;
        $total_taxes = $this->totalWithTaxes;
        $status = $this->status;
        $insert = "INSERT INTO orders (id, created, cart, customer, billing, shipping, total, total_taxes, status) VALUES (";
        $insert .= "'$id', '$created', '$cart', '$customer', '$billing', '$shipping', '$total', '$total_taxes', $status)";
        return $db->query($insert);
}

In pratica questa classe rappresenta il punto in cui sia i dati del carrello che quelli del cliente sono stati acquisiti e quindi si può procedere alla finalizzazione dell’acquisto.

Conclusione

Abbiamo visto il flusso di lavoro del nostro e-commerce attraverso le sue quattro classi principali. Nei prossimi capitoli vedremo come queste classi possono operare insieme e parleremo delle classi ausiliarie che abbiamo citato in questo capitolo.

Ti consigliamo anche