ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΕΦΗΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ

Εισαγωγή

Συχνά οι νέοι προγραμματιστές νιώθουν μπερδεμένοι όσον αφορά τον Αντικειμενοστρεφή Προγραμματισμό. Στα πρώτα βήματα μαθαίνουν έναν συγκεκριμένο τρόπο γραφής κώδικα (procedural) και όταν φτάνει ο καιρός να ασχοληθούν με Αντικεινοστρεφή Προγραμματισμό (object oriented), τότε τους φαίνεται δυσνόητη η λογική των αντικειμένων. Αυτό συμβαίνει γιατί χρειάζεται να γίνει κατανοητός ο λόγος ύπαρξης αυτής της τεχνικής η οποία χρειάζεται αρκετή υπομονή για να κατανοηθεί σωστά. Αυτός είναι ο λόγος ύπαρξης του συγκεκριμένου βοηθήματος που διαβάζετε.

Σε αυτό το κεφάλαιο θα κατανοήσετε την αιτία που χρησιμοποιούμε Αντικειμενοστρεφή Προγραμματισμό. Θα κατανοήσετε επίσης για ποιο λόγο χρησιμοποιούμε κλάσεις και αντικείμενα, καθώς και την διαφορά από τον παλαιό τρόπο προγραμματισμού (procedural) σε σχέση με τον νέο (αντικειμενοστρεφή).

Για να προχωρήσετε θα πρέπει να έχετε βασικές γνώσεις σε PHP και γενικά στον προγραμματισμό όπως: συναρτήσεις (functions), μεταβλητές (variables), συνθήκες (conditionals) και βρόγχους επαναλήψεων (loops).

Τί είναι ο Αντικειμενοστρεφής Προγραμματισμός

Για την ανάπτυξη ενός προγράμματος δεν είναι υποχρεωτικός ο Αντικειμενοστρεφής Προγραμματισμός. Τον χρησιμοποιούμε για σύνθετα προγράμματα γιατί μας βοηθά στην καλύτερη οργάνωση και διαχείριση του κώδικά μας. Συγκεκριμένα, εαν γράψετε ένα πρόγραμμα 200 γραμμών, τότε δεν είναι απαραίτητο να υλοποιηθεί σε Α/Π. Σε ένα πρόγραμμα όμως χιλιάδων γραμμών, τότε είναι απαραίτητο για την καλύτερη οργάνωση του κώδικά μας.

Με τον Αντικειμενοστρεφή Προγραμματισμό σχεδιάζουμε καλύτερα το πρόγραμμά μας. Το χωρίζουμε σε τμήματα επιτυγχάνοντας καλύτερη δομή του κώδικα. Με λίγα λόγια, με τον Α/Π γλιτώνουμε απο το απόλυτο χάος βάζοντάς τον σε τάξη τον κώδικά μας.

Στον Αντικειμενοστρεφή Προγραμματισμό κάθε κλάση (class) κάνει μια συγκεκριμένη ενέργεια. Συνεπώς, το πρόγραμμά μας το χωρίζουμε σε κλάσεις όπου η κάθε κλάση έχει συγκεκριμένο λόγο ύπαρξης και εκτελεί συγκεκριμένες εργασίες.

Πώς δημιουργούμε μια κλαση

Μια κλάση δημιουργείται χρησιμοποιώντας την λέξη class. Για παράδειγμα, για να δημιουργήσουμε μια κλάση με όνομα Account, τότε γράφουμε:

class Account     ←  Αρχή της κλάσης
{
}                 ←  Τέλος της κλάσης

Η κλάση που δημιουργήσαμε δεν κάνει προς το παρόν απολύτως τίποτα γιατί πολύ απλά δεν περικλύει καθόλου κώδικα. Απο αυτή την κλάση όμως μπορούμε να δημιουργήσουμε αντικείμενα.

Τα αντικείμενα είναι το «αντίγραφο» της κλάσης (blueprint). Απο μία κλάση μπορούν να δημιουργηθούν πολλαπλά αντικείμενα που το κάθε αντικείμενο θα έχει τον ίδιο κώδικα από την κλάση που δημιουργήθηκε.

Για παράδειγμα, μια κλάση είναι κάτι αντίστοιχο με το αρχιτεκτονικό σχέδιο ενός σπιτιού. Βάσει του αρχιτεκτινικού αυτού σχεδίου κατασκευάζουμε το σπίτι (δηλαδή το αντικείμενο). Μπορούμε βέβαια, χρησιμοποιώντας το συγκεκριμένο αρχιτεκτονικό σχέδιο να κατασκευάσουμε πολλαπλά σπίτια (δηλαδή πολλαπλά αντικείμενα).

Παρακάτω θα δημιουργήσουμε μια κλάση Account η οποία θα εκτελεί ενέργειες που πραγματοποιούνται στις τραπεζικές μας συναλλαγές:

1. <?php
2. class Αccount 
3. {
4.   //εδώ γράφουμε τον κώδικά μας
5. }
6. ?> 

Αρχικά θα αναλύσουμε τα δομικά στοιχεία που αποτελείται μια κλάση. Στην γραμμή 2 δηλώνουμε το όνομα της κλάσης μας. Στην συγκεκριμένη περίπτωση είναι η Account.

Πώς δημιουργούμε αντικείμενα

Προς το παρόν δημιουργήσαμε μια κλάση, αλλά ακόμα δεν την έχουμε χρησιμοποιήσει γιατί πολύ απλά δεν δημιουργήσαμε κανένα αντικείμενο. Παρακάτω θα δούμε πώς δημιουργούμε ένα αντικείμενο απο την κλάση Account.

<?php
$bob = new Account();
?>

Για να δημιουργήσουμε ένα νέο αντικείμενο, καλούμε την μέθοδο new. Το αντικείμενό μας πλέον έχει δημιουργηθεί και είναι το bob. Από εδώ και στο εξής, μέσα στον κώδικά μας, όποτε καλούμε το bob, θα χρησιμοποιούμε τον κώδικα που υπάρχει εντός της κλάσης Account.

Στο παραπάνω παράδειγμα δημιουργήσαμε το αντικείμενο bob απο την κλάση Account. Μπορούμε να δημιουργήσουμε πολλαπλά αντικείμενα χρησιμοποιώντας την ίδια κλάση όπως π.χ.

$maria = new Account(); 

Κάθε αντικείμενο τρέχει τον ίδιο κώδικα που έχουμε γράψει στην κλάση Account αλλά με διαφορετικές τιμές. Αυτός άλλωστε είναι ο σκοπός του Αντικειμενοστρεφούς προγραμματισμού.

Πώς ομαδοποιούμε δεδομένα

Στις κλάσεις δεν είναι απαραίτητο να αποθηκεύουμε δεδομένα, αλλά ορισμένες φορές χρειάζεται. Κάθε κλάση αποθηκεύει και τα δικά της δεδομένα όπως για παράδειγμα η Account. Στην Account εκτός απο το να αποθηκεύουμε το balance, μπορούμε να αποθηκεύσουμε το όνομα και το email του πελάτη που είναι κάτοχος του λογαριασμού. Τα δεδομένα που αποθηκεύονται στην κλάση είναι σχετικά με τον σκοπό που έχει δημιουργηθεί η κλάση.

class Account
{
  public $name;
  public $email;
  public $balance;

  function create($name, $email, $balance)
  {
    $this->name = $name;
    $this->email = $email;
    $this->balance = $balance;
  }
}

Το παράδειγμα με τον τραπεζικό λογαριασμό πλέον αρχίζει να γίνεται πιο κατανοητό. Όταν δημιουργούμε ένα αντικείμενο, δηλώνουμε περισσότερες παραμέτρους στα δεδομένα του αντικειμένου μας π.χ.

$bob = new Account("Bob", "info@bob.com", 10.00);

Ένα αντικείμενο όμως, εκτός απο τα δεδομένα, περιέχει και μεθόδους οι οποίες είναι ομαδοποιημένες σύμφωνα με τον σκοπό που δημιουργήθηκε η κλάση.

class Account
{
  public $name;
  public $email;
  public $balance;
  
  function create($name, $email, $balance)
  {
    $this->name = $name;
    $this->email = $email;
    $this->balance = $balance;
  }

  function deposit($amount)
  {
    #code
  }

  function withdraw($amount)
    #code
  }
}

Από το παραπάνω παράδειγμα αν εξαιρέσουμε τις γραμμές 9 & 13 που δεν περιέχουν κώδικα οι μέθοδοί μας, η κλάση μας αρχίζει να παίρνει πιο ολοκληρωμένη μορφή. Ο Bob πλέον, εκτός απο το ανοίγει απλά έναν λογαριασμό, μπορεί να καταθέτει ή να κάνει ανάληψη των χρημάτων από τον τραπεζικό του λογαριασμό όταν το επιθυμεί.

Η κλάση Account, είναι σχεδόν έτοιμη. Το μόνο που απομένει, είναι να ολοκληρώσουμε τις μεθόδους deposit και withdraw.

Δημιουργώντας μεθόδους

Ένα σημαντικό προτέρημα όταν δημιουργούμε μεθόδους μέσα σε κλάσεις, είναι οτι τον ίδιο κώδικα μπορούμε να τον επαναχρησιμοποιούμε ταυτόχρονα πολλές φορές δημιουργώντας αντικείμενα.

Επιπλέον, εφόσον ολοκληρωθεί η κλάση μας, τότε ο προγραμματιστής χρησιμοποιεί την μέθοδο απλώς καλώντας την μέσω του αντικειμένου που δημιουργήθηκε. Συνεπώς, τον προγραμματιστή δεν τον ενδιαφέρει πώς είναι κατασκευασμένη η μέθοδος, αλλά απλώς τί εργασία εκτελεί. Το μόνο που χρειάζεται να γνωρίζει ο προγραμματιστής, είναι οι παράμετροι της μεθόδου του αντικειμένου που έχει δημιουργήσει. Για παράδειγμα, στην κλάση Account, η μέθοδος create δέχεται τρεις παραμέτρους. Το $name, $email και $balance.

Καθώς υλοποιούμε ένα αντικείμενο, πρέπει να γνωρίζουμε ακριβώς τί θα κάνει. Για παράδειγμα η μέθοδος deposit, θα πρέπει να προσθέτει το ποσό της κατάθεσης στην μεταβλητή $balance και να αποθηκεύει το αποτέλεσμα στην $balance.

Παρακάτω θα δούμε την υλοποίηση αυτών των δύο μεθόδων.

class Account
{
  public $name;
  public $email;
  public $balance;
  
  function create($name, $email, $balance)
  {
    $this->name = $name;
    $this->email = $email;
    $this->balance = $balance;
  }

  function deposit($amount)
  {
    $this->balance += $amount;
  }

  function withdraw($amount)
    $this->balance -= $amount;
  }
}

Στο παραπάνω παράδειγμα, για να το χρησιμοποιήσουμε, πρέπει πρώτα να αρχικοποιήσουμε το αντικείμενο με δεδομένα, και στη συνέχεια να χρησιμοποιήσουμε τις μεθόδους deposit() και widthdraw().

Βέβαια, για να δούμε τις τιμές που έχει ο κάθε λογαριασμός, χρειαζόμαστε να προσθέσουμε μια ακόμα μέθοδο μέσα στην κλάση Account με όνομα display(). Η display, θα εμφανίζει τις τιμές των δεδομένων του αντικειμένου μας. Παρακάτω θα την υλοποιήσουμε και θα την χρησιμοποιήσουμε για να δείτε πώς λειτουργεί.

function display()
{
  echo "Name: " . $this->name;
  echo "Email: " . $this->email;
  echo "Balance: " . $this->balance;
}

Στο σημείο αυτό, μπορούμε να εκτελέσουμε το παράδειγμα με τον παρακάτω κώδικα.

$bob_account = new Account();
$maria_account = new Account();

$bob_account->create('Bob', 'info@microsoft.com', 100);
$maria_account->create('Maria', 'info@apple.com', 200);

$bob_account->deposit(200);
$maria_account->deposit(300);

$bob_account->display();
$maria_account->display();
Αποτέλεσμα:

Name: Bob
Email: info@microsoft.com
Balance: 300

Name: Maria
Email: info@apple.com
Balance: 500

Παρακάτω θα βρείτε τον κώδικα ολοκληρωμένο:

<?php
class Account
{
    public $name = '';
    public $email = '';
    public $balance = 200;

    function create($name, $email, $balance)
    {
        $this->name = $name;
        $this->email = $email;
        $this->balance = $balance;
    }

    function deposit($amount)
    {
        $this->balance += $amount;
    }

    function withdraw($amount)
    {
        $this->balance -= $amount;
    }

    function display()
    {
        echo "Name: " . $this->name;
        echo "Email: " . $this->email;
        echo "Balance: " . $this->balance;
    }

}

$bob_account = new Account();
$maria_account = new Account();

$bob_account->create('Bill', 'info@microsoft.com', 100);
$maria_account->create('Maria', 'info@apple.com', 200);

$bob_account->deposit(200);
$maria_account->deposit(300);

$bob_account->display();
$maria_account->display();

?>

Constructors

Ο constructor είναι μια “ειδική” function η οποία εκτελείται αυτόματα όταν δημιουργείται ένα αντικείμενο (object). Κάθε φορά που δημιουργόύμε ένα αντικείμενο, καλείται τουλάχιστον ένας constructor. Σε περίπτωση που δεν δημιουργήσουμε κάποιον constructor, τότε η php δημιουργεί έναν default constructor. Οι constructors είναι χρήσιμοι για να αρχικοποιούμε τις τιμές του αντικειμένου μας.

Κανόνες δημιουργίας των constructors:

  • Ο constructor δεν πρέπει να επιστρέφει κάτι (δεν χρησιμοποιείται η return).
  • Δεν μπορεί να είναι abstract, static, final.

Οι constructors δημιουργούνται στην php με την __construct().

class Person 
{
  var $name;

  function __construct($persons_name) 
  {
    $this->name = $persons_name;
  }

  function set_name($new_name) 
  {
    $this->name = $new_name;  
  }

  function get_name() 
  {
    return $this->name;
  }
} 

Στην ορολογία του Αντικεμενοστρεφούς προγραμματισμού όπου functions χρησιμοποιούμε methods και όπου variables χρησιμοποιούμε properties.

Έτσι, από εδώ και στο εξής θα ισχύει το παρακάτω:

Functions = Methods
Variables = Properties

Παρακάτω θα δημιουργήσουμε ένα αντικείμενο χρησιμοποιώντας τον παραπάνω constructor της κλάσης Person:

$andreas = new Person("Andreas Bourakis");
echo "Andreas's full name: " . $andreas->get_name();

Κληρονομικότητα

Στον Αντικειμενοστρεφή Προγραμματισμό όταν μια κλάση προέρχεται από μια άλλη κλάση, τότε αυτό είναι η κληρονομικότητα (inheritance). Η προερχόμενη κλάση ονομάζεται child, ενώ η κλάση που προέρχεται η child λέγεται parent class (ορισμένες φορές τις αποκαλούμε sub και super κλάση αντίστοιχα). Γενικά η child class προέρχεται (extends) από την parent class. Παρακάτω παρουσιάζεται ένα παράδειγμα κληρονομικότητας.

<?php
class Person 
{
	public $name;
	public $age;

	public function __construct($name, $age) 
	{
        $this -> name = $name;
        $this -> age = $age;
	}

	public function introduce() 
	{
	    echo "My name is {$this -> name}. My age is {$this -> age}";
	}
}

/* Tom is inherited from Person */
class Tom extends Person 
{
	# __construct() is inherited
	# introduce() is inherited

	public function sayHello() 
	{
	    echo "Hello, World <br>";
	}
}

$tom = new Tom('Tom', 29);
$tom -> sayHello();
$tom -> introduce();

Αποτέλεσμα:

Hello, World
My name is Tom. My age is 29

Γιατί κληρονομικότητα;

Η κληρονομικότητα είναι πολύ σημαντική στον Αντικειμενοστρεφή Προγραμματισμό γιατί μας βοηθά να αποφεύγουμε τον επαναλαμβανόμενο κώδικα. Με αυτό τον τρόπο επιτυγχάνεται καλύτερη διαχείριση περίπλοκων και μεγάλων διαδικασιών.

Overriding inherited Methods

Το overriding το χρησιμοποιούμε όταν θέλουμε να εκτελέσουμε τις μεθόδους της child class και οχι τις μεθόδους της parent class. Για να επιτευχθεί αυτό, τα ονόματα των μεθόδων στην child class πρέπει να είναι ίδια με εκείνα της parent class. Αυτό μας βοηθά να γράφουμε ευέλικτο κώδικα και ανάλογα με την κλάση που επιλέγουμε για να δημιουργήσουμε το object (parent class ή child class), αυτόματα εκτελείται και η αντίστοιχη μέθοδος.

<?php

class Person 
{
    public $name;
    public $age;
    
    public function __construct($name, $age) 
    {
        $this -> name = $name;
        $this -> age = $age;
    }
    
    public function introduce() 
    {
        echo "My name is {$this -> name}. My age is {$this -> age}";
    }
}

class Tom extends Person 
{
    public $school;
    
    // overriden method
    public function __construct($name, $age, $school) 
    {
        $this -> name = $name;
        $this -> age = $age;
        $this -> school = $school;
    }
    
    public function introduce() 
    {
        echo "My name is {$this -> name}. My age is {$this -> age}. My school is {$this -> school}";
    }
}

$tom = new Tom('Tom', 29, 'Foothill School');
$tom -> introduce();

Αποτέλεσμα:

My name is Tom. My age is 29. My school is Foothill School

Όταν κάνουμε override τη μέθοδο της parent class, για να καλέσουμε την μέθοδο από την child class που βρίσκεται στην parent class δεν μπορούμε να χρησιμοποιήσουμε το $this->methodName, αλλά το parent::methodName (όπου methodName είναι το όνομα της μεθόδου μας).

Final

Η εντολή final έχει δύο χρήσεις. Η πρώτη είναι να αποτρέψει να κληρονομηθεί μια κλάση από μια άλλη κλάση. Η δεύτερη είναι η αποτροπή να γίνει μια μέθοδος override.

Αποτροπή κληρονομικότητας:

final class NonParent 
{
    // class code
}

// will throw an error
class Child extends NonParent {...}

Αποτροπή override μεθόδου:

class ParentClass 
{
    final public function myMethod() 
    {

    }
}
class Child extends ParentClass 
{
    // Fatal Error: Overriding final methods
    public function myMethod() 
    {

    }
}

Properties access modifiers

Μία απο τις βασικές αρχές του Αντικειμενοστρεφούς προγραμματισμού είναι η ενθυλάκωση (encapsulation). Με την ενθυλάκωση επιτυγχάνουμε ευανάγνωστο και ποιοτικότερο κώδικα εφόσον μπορούμε να θέτουμε περιορισμούς στην πρόσβαση των properties. Στην php υπάρχουν 3 modifiers.

  1. public
  2. private
  3. protected

Public

Η public είναι ο default modifier. Αυτό σημαίνει πως αν δεν δηλώσουμε το visibility ενός property ή μιας function, τότε λειτουργεί ως public. Τα public στοιχεία μπορούν να είναι προσβάσιμα:

  • Έξω απο την κλάση μας
  • Εντός της κλάσης μας
  • Από μια άλλη κλάση η οποία γίνεται implement
class Person 
{
  var $name;
  public $height;
  protected $social_insurance;
  private $pinn_number;

  function __construct($persons_name) 
  {
    $this->name = $persons_name;
  }

  function set_name($new_name) 
  {
    $this->name = $new_name;
  }

  function get_name() 
  {
    return $this->name;
  }
}

Σημείωση: Όταν δηλώνουμε μια μεταβλητή με την var, τότε αυτομάτως το property είναι public.

Private

Όταν δηλώνουμε ένα property ως private, τότε περιορίζουμε την πρόσβαση μόνο εντός της κλάσης για το συγκεκριμένο property που δηλώθηκε ως private. Αυτό σημαίνει πως σε περίπτωση που κληρονομηθεί η συγκεκριμένη κλάση από μια άλλη κλάση, τότε το στοιχείο που είναι private δεν θα μπορεί να χρησιμοποιηθεί.

class MyClass 
{
   private $car = "Lada";
   $driver = "Andreas";
   
   function __construct($par) 
   {
      // Statements here run every time
      // an instance of the class
      // is created.
   }
   
   function myPublicFunction() 
   {
      return("I'm visible!");
   }
   
   private function myPrivateFunction() 
   {
      return("I'm  not visible outside!");
   }
}

Στο παραπάνω παράδειγμα εαν η κλάση MyClass κληρονομηθεί από άλλη κλάση, τότε η private function με όνομα myPrivateFunction() δεν θα είναι ορατή και συνεπώς δεν θα μπορεί να χρησιμοποιηθεί. Το ίδιο ισχύει και για το property $car.

Protected

Όταν ένα property είναι δηλωμένο ως protected, τότε μόνο η ίδια κλάση και οι κλάσσεις οι οποίες προκύπτουν από αυτή την κλάση έχουν πρόσβαση στο συγκεκριμένο property. Αυτό έχει να κάνει καθαρά με την κληρονομικότητα.

class MyClass 
{
   protected $car = "skoda";
   $driver = "SRK";

   function __construct($par) 
   {
      // Statements here run every time
      // an instance of the class
      // is created.
   }
   
   function myPublicFunction() 
   {
      return("I'm visible!");
   }
   
   protected function myPrivateFunction() 
   {
      return("I'm  visible in child class!");
   }
}

Static

Ένα μέλος (μεταβλητή ή συνάρτηση) μιας κλάσης μπορεί να χαρακτηριστεί ως static. Κάθε static μέλος έχει δύο βασικά χαρακτηριστικά:

  1. Η πρόσβασή του είναι άμεση χωρίς να χρειαστεί πρώτα να δημιουργηθεί κάποιο αντικείμενο.
  2. Όλα τα αντικείμενα που έχουν δημιουργηθεί με βάση μια συγκεκριμένη κλάση, μοιράζονται τα static μέλη της κλάσης. Δηλαδή μια static μεταβλητή είναι κοινή για όλα τα αντικείμενα της κλάσης.

Έτσι, αν για παράδειγμα αλλάξει η τιμή της μεταβλητής, τότε αυτή η τιμή περνάει σε όλα τα αντικείμενα που έχουν δημιουργηθεί από αυτή την κλάση.

Σε ένα πιο πρακτικό παράδειγμα μπορεί να έχουμε μια κλάση έστω Product που περιέχει μια static μεταβλητή έστω $fpa στην οποία αποθηκεύεται η τιμή του Φ.Π.Α. και η οποία είναι ίδια για όλα τα προϊόντα. Αν τώρα αλλάξει η τιμή του φπα, απλά αλλάζουμε την τιμή της static $fpa και επειδή είναι κοινή για όλα τα προϊόντα, όλα τα προϊόντα θα ενημερωθούν αυτόματα.

Ένα static μέλος μπορεί να είναι public, private ή protected. Τέλος, η αναφορά σε ένα static μέλος, μέσα από την κλάση, γίνεται με τη λέξη self:: αντί του $this->. Σε νεότερες εκδόσεις της php μπορείτε να χρησιμοποιήσετε και την static:: αντί της self::.

Το παρακάτω παράδειγμα δείχνει πως μπορείτε να έχετε πρόσβαση σε μια static μεταβλητή χρησιμοποιώντας το όνομα της κλάσης και όχι με τη χρήση αντικειμένου.

<?php
class Product
{
  static $fpa = 23;
}

echo Product::$fpa;
?>

Αποτέλεσμα:

23

Το παρακάτω παράδειγμα δείχνει πως διαφορετικά αντικείμενα μοιράζονται την ίδια static μεταβλητή.

<?php

class Product
{	
  static $fpa = 23;
  
  function get_fpa()
  {
    //return self::$fpa;
    return static::$fpa;
  }
}

$milk = new Product();
$bread = new Product();

echo $milk->get_fpa() . " - " . $bread->get_fpa() . "<br />";
Product::$fpa=19;

echo $milk->get_fpa() . " - " . $bread->get_fpa();
?>

Αποτέλεσμα:

23 – 23
19 – 19

Const / Σταθερές

Σε μία κλάση μπορούμε να δηλώσουμε μια μεταβλητή ως σταθερή με την λέξη const.

class Product
{
  const FPA=0.23;
}

Όταν δηλώνετε μια μεταβλητή (έστω την FPA) ως σταθερή, δεν χρησιμοποιείτε το $. Επίσης στην σταθερή πρέπει να δώσετε και αρχική τιμή. Μια σταθερή δεν μπορεί να είναι private, public ή protected αλλά μόνο public εξ’ ορισμού. Για να έχετε πρόσβαση στην τιμή της μεταβλητής γράφετε:

Product::FPA;

Δηλαδή το όνομα της κλάσης, τον τελεστή :: και το όνομα της σταθεράς. Ισχύει δηλαδή ό,τι ισχύει και για τις static μεταβλητές. Επίσης για να έχετε πρόσβαση στη μεταβλητή μέσα από μια συνάρτηση της κλάσης χρησιμοποιείτε πάλι (όπως και στις static) τη λέξη self::. Δηλαδή γράφετε self::FPA και όχι $this->FPA.

<?php
class Product
{  
  const FPA = 0.23;
  
  function getFPA()
  {    
    return self::FPA;  
  }
}

echo Product::FPA;

$p1 = new Product();

echo $p1::FPA;
echo $p1->getFPA(); 

?>

Στο παραπάνω παράδειγμα και οι τρεις echo δίνουν το ίδιο αποτέλεσμα (0.23).

Μια υποκλάση κληρονομεί τις σταθερές της υπερκλάσης αλλά μπορεί επίσης να δημιουργήσει τις δικές της σταθερές ή και να υπερκαλύψει τις κληρονομημένες σταθερές.

<?php
class Milk extends Product 
{
  const FPA=0.19;
  const SkimMilkFPA = 0.15;
  
  function get_parent_FPA()
  {
    return parent::FPA;  
  } 
}

echo Milk::FPA;
echo Milk::SkimMilkFPA;

$m = new Milk();

echo $m->getFPA();
echo $m->get_parent_FPA();
?>

Αποτέλεσμα:

0.19
0.15
0.23
0.23