OOP in PHP under 30 Minutes

In PHP by Hafiz Faraz MukhtarLeave a Comment

This is a quick tutorial on object-oriented programming (OOP) in PHP. There are two parts to this tutorial.

Target Audience: Developers who know procedural PHP but want to quickly learn about OOP in PHP.

Class

A class is just a definition of an object. Every class definition begins with the keyword class followed by the class name. Then you have curly braces that surround the class definition. Here I am defining a student class and making use of two built-in methods:

  1. get_declared_classes shows list of declared classes
  2. class_exists checks if a class exist
<?php
class Student
{
//class definition	
}

// prints a list of defined classes
$declaredClasses = get_declared_classes();
echo "declared classes are ". implode ("<br>", $declaredClasses);

// checks if a class exists
if(class_exists('Student')) 
	echo "class exists";
else
	echo "nop";
?>

Instance

In general use, an instance is a single occurrence of something. When we’re talking about object-oriented programming, that single occurrence of something is a single instance created from a class definition. Instance and object are used interchangeably but technically instance is the correct term. An instance is created using new keyword followed by class name. It is also called instantiation. We will be making use of a built-in method for instances:

  1. get_class gets the class name from instance
<?php	
class Student {	
// class definition 
}

// creating two instances
$student1 = new Student;
$student2 = new Student;

// Get class name of instance
echo get_class($student2);

?>

Class Properties

Class properties are variables that hold instance values. Class properties are also called class attributes or instance attributes. Below we are setting class properties inside class definition and referring it through an instance. We will be using three built-in functions as well:

  1. get_class_vars gets class properties
  2. get_object_vars gets instance properties
  3. property_exists checks property existence in a class
<?php
class Student { // class definition
		
	// class properties - we put 'var' before them
	var $name;
	var $age;
	var $school = "DPS";
	var $country = "NONE";
}

$student1 = new Student; // class instance
$student1->name = "Hafiz";// referring class property with instance
echo $student1->name." studied at ".$student1->school.".";

echo "<pre>".print_r(get_class_vars('Student'))."</pre>"; // list of class properties
echo "<pre>".print_r(get_object_vars($student1))."</pre>"; // list of class instance properties


if(property_exists($student1, 'age')) // class property exists through instance
	echo "class property exists.";
else
	echo "class property does not exist.";
?>

Class Methods

When we define a function inside a class definition it is called a class method. Some people call it class function but the class method is a more appropriate term. We will make use of two functions here:

  1. get_class_methods gets class methods
  2. method_exists checks method existence in a class definition
<?php
class Student { // class definition

	// class properties
	var $name;
	var $age;
	var $school = "DPS";
	var $country = "NONE";

	function showText(){ // class method
		return "hello I am working from class definition";
	}
}

$student1 = new Student; // class instance
$student1->name = "Hafiz";
echo $student1->name." studied at ".$student1->school;
// Output: Hafiz studied at DPS

echo $student1->showText(); // calling class method
// Output: hello I am working from class definition
	
echo "<pre>".print_r(get_class_methods('Student'))."</pre>";; // Show class methods

if(method_exists('Student', 'show')) // method in class definition
	echo "Method exists";
else
	echo "Method does not exists";
?>

Refer an instance

Refer an instance means when we call a class method it must refer to the “instance properties” instead of “class properties”.

  1. $this-> used inside the class to refer the instance properties only. This means if there are several instances each one will have its separate instance properties.
  2. $variable_name-> used outside class to refer to object properties
<?php
class Student { // class definition

	// class properties
	var $name;
	var $age;
	var $school = "DPS";
	var $country = "NONE";

	function fullName(){ // class method
		// referring class properties of instance from class method
		return " ".$this->name." is ".$this->age;
	}
}
	
$student1 = new Student; // class instance
$student1->name = "Hafiz";
$student1->age = 29;
echo $student1->name." studied at ".$student1->school;
// Output: Hafiz studied at DPS

echo $student1->fullName(); // instance calling class method
// Output: Hafiz is 29

echo "<pre>".print_r( get_object_vars ($student1))."</pre>";; // list instance properties
?>

Inheritance & Subclass

When a new class takes on properties and methods of an existing class, is called class inheritance or simply inheritance. The class which inherits from a parent class is also called a subclass. Inheritance prevents code repetition by organizing code. We are defining three classes i.e User, dealer, consultant. 

The user is the parent class. Dealer is inheriting everything from User class and then the consultant is inheriting everything from dealer class. So the hierarchy becomes, the dealer is a subclass of user and consultant is a subclass of the dealer.

We will be making use of the following functions:

  1. get_parent_class() gets the name of parent class from class instance.
  2. class_parents() shows a list of parent classes
  3. is_subclass_of() checks if the class of current instance is a subclass of a parent class
<?php
class user { // class definition

	var $name; // class property
	var $location; // class property

	function createSentence () { // class method
		// referring class properties of instance from class method
		return "The user ".$this->name." is from ".$this->location." and phone is".$this->phone."<br>";
	}
}

class dealer extends user { // subclass of user - inheriting
	var $phone; // class property
}

class consultant extends dealer { // subclasss of dealer - inheriting
	function createSentence () { // class method
		// referring class properties of instance from class method
		return "<br>The user ".$this->name." phone is ".$this->phone;
	}
}

$u = new user; // class instance
$u->name = 'Hafiz';
$u->location = 'Pakistan';
echo $u->createSentence();
// Notice: Undefined property: user::$phone
// Output: The user Hafiz is from Pakistan and phone is

$d = new dealer; // class instance
$d->name = 'Haseeb';
$d->location = 'India';
$d->phone = '12345678';
echo $d->createSentence();
// Output: The user Haseeb is from India and phone is12345678

$c = new consultant; // class instance
$c->name = "Faraz";
$c->phone = "111222333";
echo $c->createSentence();
// Output: The user Faraz phone is 111222333

print_r(get_parent_class($c)); // parent class from instance
// Output: dealer

echo "<pre>".print_r(class_parents($c))."</pre>"; // list parent classes from instance

echo is_subclass_of($c, 'User'); // Check if its a subclass
// Output: 1
?>

Visibility Modifiers

Visibility modifiers are used to control access to objects, properties, and methods. There are three visibility modifiers.

  1. Public accessible from anywhere
  2. Protected accessible from class and subclasses
  3. Private accessible from the class only

Let’s see how to use them:

<?php
class Student { // class definition

	// class properties
	public  $name; // accessible outside class
	public  $age;  // accessible outside class
	public  $school = "DPS"; // accessible outside class
	private  $country = "Pakistan"; // inaccessible outside class
	
	// protected class method - accessible from subclass
	protected function showText($name){ 
		// calling private method
		return "<br>hello I am <b>{$this->showName($name)}</b>"; 
	}

	// private class method - accessible from own class only
	private function showName($name) {  // private class method
		return $this->name." Sir";
	}
}

class parttimeStudent extends Student { // subclass of Student	
	function callProtected($name) {  // public class method 
		return $this->showText($name); // calling protected method
	}
}

$student1 = new parttimeStudent; // class instance
$student1->name = "Hafiz"; 
echo $student1->callProtected('asdfadf'); // calling public method
?>

Overriding

When subclass redeclares class properties or class method in its definition which are previously defined in the parent class, this redeclaration is called overriding. For example, if there is class of “Citizen” we can extend its properties age, occupation and education to another class called “SeniorCitizen”. This way we can add more properties to class “SeniorCitizen” without effecting the citizen class. This redeclaration of any property or method of parent class inside the “SeniorCitizen” class will be called overriding.

<?php
class citizen
{
   var $age = 1;
   var $occupation;
   var $education;
   
   function do_something() {
      echo "I am a citizen";
   }
}

// extending properties and methods to seniorCitizen
class SeniorCitizen extends citizen {
   var $retired = true;

   // Overriding 
   function do_something() {
      echo "I am a senior citizen and my age is $this->age";
   }
}

$user = new SeniorCitizen;
// Inheriting class property 'age' from citizen class
$user->age = 42;
$user->do_something();

/* output: I am a senior citizen and my age is 42 */
?>

Overloading

Overloading is a feature of PHP that handles calls to properties and methods which do not exist or are not visible. So here’s an example:

<?php
class member {
  // no class property exists in class
}

$person = new member;
echo $person->name; 	 // undefined property because property do not exist

$person->name = "faraz"; // overloading, we explicitly defined it
echo $person->name; 	 // faraz

?>

Setter and getter methods

So far we have been interacting with class properties directly. A good practice is to access class properties through setter method and read through a getter method. This is how it is done:

<?php
class Student { 
   
   private $name;
   
   // setter - setting private property value
   public function setter_method($value) {
      $this->name = $value;
   }

   // getter - processing private property value
   public function getter_method() { 
        echo $this->name; 
        return $this->name; 
   }
}

$std = new Student;
$std->setter_method("John");
$std->getter_method();

?>

Static Modifiers

Static modifiers are properties and methods which we can access inside and outside class without creating an instance. In order to define them, we’re going to use the keyword static. So for example, if I have a “user” class, I can have a static property for grades by putting the static keyword in front of it.

Important: Inherited static properties are shared values. That means its value can be changed from anywhere.

Here is a simple example:

<?php
class user {

   private static $client = 0; // static inside class
   public static $lead = 0;    // static outside class

   private static function add_client () {
   // accessing static property inside class using self::
      return self::$client += 1; 
   }
   private static function add_lead () {
   // accessing static property inside class using self::
      return self::$lead += 1;
   }

   public static function is_admin ($action) {
      switch($action) {
         case 'add_client':
         return self::add_client();
         break;

	 case 'add_lead':
	 return self::add_lead();
	 break;
      }
   }

}

//calling static method from class
$clients = user::is_admin("add_client");
$clients = user::is_admin("add_client");
$lead = user::is_admin("add_lead");
echo "Total clients are ".$clients."<br>";
echo "Total leads are ".$lead."<br>";
echo "Directly accessing number of leads ". user::$lead;

/* output:
Total clients are 2
Total leads are 1
Directly accessing number of leads 1
*/

?>

Class constants

The class constant is the opposite of static modifiers. That is their value remains constant and cannot be changed.

In this example, I am defining a class constant called “paymentReminder” that sets a 60 minutes reminder to make payment from the time you place an order. Here is the code:

<?php

class user {
   public const paymentReminder = 60*60;

   public static function invoiceGenerated () {
      // Takes current time and adds 60 minutes through class constant.
      return time() + self::paymentReminder;;
   }
} 

$reminderSent = user::invoiceGenerated();
echo "current time is "
	.gmdate('H:m',time())
	." reminder will be sent in one hour at "
	.gmdate('H:m', $reminderSent);

/* Output: current time is 16:01 reminder will be sent in one hour at 17:01
NOTE: your output will differ due to time */
?>

 

Referring parent class

When referring parent class from the subclass, we have two options:

  1. Use class name to refer e.g user::paymentReminder (as we did above)
  2. Refer parent class using ‘parent’ keyword e.g  parent::paymentReminder (considered best practice)

In the example below, I am accessing static class property $resizing_enabled setting its value false. Using simple if/else statement referring parent class method.

<?php 

class image {
	public static $resizing_enabled = true;

	protected static function resize_image() {
		echo '800 x 600';
	}
}

class thumbnail extends image {

	public static function resize_image() {
		if(self::$resizing_enabled) {
			echo '100 x 100';
		}
		else {
			// referring parent class method
			parent::resize_image();
		}
	}
}


image::$resizing_enabled = false;
thumbnail::resize_image();

?>

Late Static Binding

At this point, we know that the “self” keyword is used to reference the called class properties or methods. Before explaining late static binding, let’s see a problem with “self”.

Problem: Static references to the current class like self:: are resolved using the class in which the function belongs, as in where it was defined, neglecting referred class defintions.

<?php 
class user {
	protected static $name = "ABC";

	public static function showName () {
		echo self::$name;
	}

}

class dev extends user {
	protected static $name = "XYZ";
}


user::showName();
dev::showName(); 
/* Output
----------
user : ABC
dev : ABC 
----------
this is the problem you see "self" limitation? XYZ is being ignored in dev class definition */
?>

Solution: Swap “self” with “Static”.

“Static::” references the class that was initially called at runtime and hence shows result from there.

class user {
	protected static $name = "ABC";

	public static function showName () {
		echo "<br>".get_called_class() ." : ";
		echo static::$name;
	}

}

class dev extends user {
	protected static $name = "XYZ";
}


user::showName();
dev::showName(); 
/* Output 
---------- 
user : ABC
dev : XYZ
----------
Now fine, dev name is now XYZ, this is late static binding*/
?>

 

About the Author
Hafiz Faraz Mukhtar

Hafiz Faraz Mukhtar

Facebook Twitter

Hafiz Faraz Mukhtar is an expert Web Developer, SEO specialist, and Graphic Designer. Hafiz Faraz is an expert in WordPress design and development. If you would like to hire him, here is his Upwork profile link: https://www.upwork.com/fl/hfarazm

Leave a Comment