Saturday, 5 August 2017

OOPS

Classes, objects, methods and properties
Object-oriented programming is a programming style in which it is customary to group all of the variables and functions of a particular topic into a single class. Object-oriented programming is considered to be more advanced and efficient than the procedural style of programming. This efficiency stems from the fact that it supports better code organization, provides modularity, and reduces the need to repeat ourselves. That being said, we may still prefer the procedural style in small and simple projects. However, as our projects grow in complexity, we are better off using the object oriented style.
With this tutorial, we are going to take our first steps into the world of object oriented programming by learning the most basic terms in the field:
·         classes
·         objects
·         methods
·         properties
You'll learn   
·         How to create classes?
·         How to add properties to a class?
·         How to create objects from a class?
·         How to get and set the objects' properties?
·         How to add methods to a class?
How to create classes?
In order to create a class, we group the code that handles a certain topic into one place. For example, we can group all of the code that handles the users of a blog into one class, all of the code that is involved with the publication of the posts in the blog into a second class, and all the code that is devoted to comments into a third class.
To name the class, it is customary to use a singular noun that starts with a capital letter. For example, we can group a code that handles users into a User class, the code that handles posts into a Post class, and the code that is devoted to comments into a Comment class.
For the example given below, we are going to create a Car class into which we will group all of the code which has something to do with cars.
class Car {
  // The code
}
·         We declare the class with the class keyword.
·         We write the name of the class and capitalize the first letter.
·         If the class name contains more than one word, we capitalize each word. This is known as upper camel case. For example, JapaneseCarsAmericanIdolEuropeTour, etc.
·         We circle the class body within curly braces. Inside the curly braces, we put our code.
How to add properties to a class?
We call properties to the variables inside a class. Properties can accept values like strings, integers, and booleans (true/false values), like any other variable. Let's add some properties to the Car class.
class Car {
  public $comp;
  public $color = 'beige';
  public $hasSunRoof = true;
}
·         We put the public keyword in front of a class property.
·         The naming convention is to start the property name with a lower case letter.
·         If the name contains more than one word, all of the words, except for the first word, start with an upper case letter. For example, $color or $hasSunRoof.
·         A property can have a default value. For example, $color = 'beige'.
·         We can also create a property without a default value. See the property $comp in the above example.
How to create objects from a class?
We can create several objects from the same class, with each object having its own set of properties.
In order to work with a class, we need to create an object from it. In order to create an object, we use the new keyword. For example:
$bmw = new Car ();
·         We created the object $bmw from the class Carwith the new keyword.
·         The process of creating an object is also known as instantiation.
We can create more than one object from the same class.
$bmw = new Car ();
$mercedes = new Car ();
In fact, we can create as many objects as we like from the same class, and then give each object its own set of properties.
Objects, what are they good for?
While in the procedural style of programming, all of the functions and variables sit together in the global scope in a way that allows their use just by calling their name, the use of classes makes anything inside the classes hidden from the global scope. That's because the code inside the classes is encapsulated within the class scope, outside the reach of the global scope. So, we need a way to allow the code from the global scope to use the code within the class, and we do this by creating objects from a class.
I say objects, and not object, because we can create as many objects as we would like from the same class and they all will share the class's methods and properties. See the image below:
Objects and classes in object oriented PHP through a car exampleFrom the same Car class, we created three individual objects with the name of: MercedesBmw, and Audi.
Although all of the objects were created from the same class and thus have the class's methods and properties, they are still different. This is not only, because they have different names, but also because they may have different values assigned to their properties. For example, in the image above, they differ by the color property - the Mercedes is green while the Bmw is blue and the Audi is orange.
THE MESSAGE TO TAKE HOME IS:
A class holds the methods and properties that are shared by all of the objects that are created from it.
Although the objects share the same code, they can behave differently because they can have different values assigned to them.
How to get an object's properties?
Once we create an object, we can get its properties. For example:
echo $bmw -> color;
echo $mercedes -> color;
·         In order to get a property, we write the object name, and then dash greater than (->), and then the property name.
·         Note that the property name does not start with the $ sign; only the object name starts with a $.
Result:beige
beige
How to set the object's properties?
In order to set an object property, we use a similar approach.
For example, in order to set the color to 'blue' in the bmw object:
$bmw -> color = 'blue';
and in order to set the value of the $comp property for both objects:
$bmw -> comp = "BMW";
$mercedes -> comp = "Mercedes Benz";
Once we set the value of a property, we can get its value.
In order to get the color of the $bmw object, we use the following line of code:
echo $bmw -> color;
Result:blue
We can also get the company name and the color of the second car object.
echo $mercedes -> color;
echo $mercedes -> comp;
Result:beige
Mercedes Benz
How to add methods to a class?
The classes most often contain functions. A function inside a class is called a method. Here we add the method hello()to the class with the prefix public.
class Car {

  public $comp;
  public $color = 'beige';
  public $hasSunRoof = true;

  public function hello()
  {
    return "beep";
  }
}
·         We put the public keyword in front of a method.
·         The naming convention is to start the function name with a lower case letter.
·         If the name contains more than one word, all of the words, except for the first word, start with an upper case letter. For example, helloUser() or flyPanAm().
We can approach the methods similar to the way that we approach the properties, but we first need to create at least one object from the class.
$bmw = new Car ();
$mercedes = new Car ();
   
echo $bmw -> hello();
echo $mercedes -> hello();
Result:beep
beep
Here is the full code that we have written during this tutorial:
<?php
// Declare the class
class Car {

  // properties
  public $comp;
  public $color = 'beige';
  public $hasSunRoof = true;

   // method that says hello
  public function hello()
  {
    return "beep";
  }
}

// Create an instance
$bmw = new Car ();
$mercedes = new Car ();

// Get the values
echo $bmw -> color; // beige
echo "<br />";
echo $mercedes -> color; // beige
echo "<hr />";

// Set the values
$bmw -> color = 'blue';
$bmw -> comp = "BMW";
$mercedes -> comp = "Mercedes Benz";

// Get the values again
echo $bmw -> color; // blue
echo "<br />";
echo $mercedes -> color; // beige
echo "<br />";
echo $bmw -> comp; // BMW
echo "<br />";
echo $mercedes -> comp; // Mercedes Benz
echo "<hr />";

// Use the methods to get a beep
echo $bmw -> hello(); // beep
echo "<br />";
echo $mercedes -> hello(); // beep


The $this keyword

In the first tutorial of this series, we learned how to group the code related to a certain topic into one single class. As an example, we wrote a Car class that groups the code that handles cars.
class Car {



  public $comp;
  public $color = 'beige';
  public $hasSunRoof = true;
 
  public function hello() 
  {
    return "beep";
  }
}
We also created two objects out of the class in order to be able to use its code.
$bmw = new Car ();
$mercedes = new Car ();
You'll learn   
·         Why use the $this keyword?
·         How to use the $this keyword to approach the class's own properties and methods from within the class?

 

The $this keyword

The $this keyword indicates that we use the class's own methods and properties, and allows us to have access to them within the class's scope.
The $this keyword allows us to approach the class properties and methods from within the class using the following syntax:
·         Only the $this keyword starts with the $ sign, while the names of the properties and methods do not start with it.
$this -> propertyName;
$this -> methodName();
The $this keyword indicates that we use the class's own methods and properties, and allows us to have access to them within the class's scope.
Let's illustrate what we have just said on the Car class. We will enable the hello() method to approach the class's own properties by using the $this keyword.
In order to approach the class $comp property. We use:
$this -> comp
In order to approach the class $color property. We use:
$this -> color
That's what the code looks like:
class Car {



    // The properties
    public $comp;
    public $color = 'beige';
    public $hasSunRoof = true;
 
    // The method can now approach the class properties
    // with the $this keyword
    public function hello()
    {
      return "Beep I am a <i>" . $this -> comp . "</i>, and I am <i>" .
        $this -> color;
    }
}
Let us create two objects from the class:
$bmw = new Car();
$mercedes = new Car ();
and set the values for the class properties:
$bmw -> comp = "BMW";
$bmw -> color = "blue";
 
$mercedes -> comp = "Mercedes Benz";
$mercedes -> color = "green";
We can now call the hello() method for the first car object:
echo $bmw -> hello();
Result:
Beep I am a BMW, and I am blue.
And for the second car object.
echo $mercedes -> hello();
Result:
Beep I am a Mercedes Benz, and I am green.
This is the code that we have written in this tutorial:
 class Car {



    // The properties
    public $comp;
    public $color = 'beige';
    public $hasSunRoof = true;
 
    // The method that says hello
    public function hello()
    {
      return "Beep I am a <i>" . $this -> comp . 
         "</i>, and I am <i>" . $this -> color;
    }
}
 
// We can now create an object from the class.
$bmw = new Car();
$mercedes = new Car();
 
// Set the values of the class properties.
$bmw -> color = 'blue';
$bmw -> comp = "BMW";
$mercedes -> comp = "Mercedes Benz";
 
// Call the hello method for the $bmw object.
echo $bmw -> hello();




Chaining methods and properties

In the previous tutorial, we learned to use the $this keyword to approach properties and methods within the scope of the class. In this chapter we will learn that, when a class's methods return the $thiskeyword, they can be chained together to create much more streaming code.
For instance, in our Car class, let's say that we want to measure how much fuel we have in our car's tank. The amount of fuel in the tank is dependent upon the number of miles we have driven in our car, as well as the amount of fuel that we put in the tank.
In order to achieve our goal, we are going to put a public property $tankto our class that represents the number of gallons of fuel that we have in the car's tank.
class Car {
  public $tank;
}
You'll learn   
·         How to chain methods and properties?
·         Why do we want to chain methods and properties?
We must also add two methods to our Car class:
1. The fill() method adds gallons of fuel to our car's tank.
2. The ride() method calculates how much fuel we consume when we ride a certain distance, and then subtracts it from the tank. In our example, we assume that the car consumes 1 gallon of fuel every 50 miles.
class Car {
 
  public $tank;
 
  // Add gallons of fuel to the tank when we fill it.
  public function fill($float)
  {
    $this-> tank += $float;
  }
  
  // Substract gallons of fuel from the tank as we ride the car.
  public function ride($float)
  {
    $miles = $float;
    $gallons = $miles/50;
    $this-> tank -= $gallons;
  }
}
As we would like our code to look elegant, we will chain the methods and properties. Note the arrows in the code.
 1$tank = $car -> fill(10) -> ride(40) -> tank;
In words: How much fuel do we have left in our tank after putting in 10 gallons, and driving 40 miles?
In order for us to be able to perform the chaining, the methods should return the object and, since we are inside the class, the methods should return the $this keyword.
In the code below, we can see how each method returns the $this keyword in order to allow the chaining.
class Car {
 
  public $tank;
  
  // Add gallons of fuel to the tank when we fill it.
  public function fill($float)
  {
    $this-> tank += $float;
 
    return $this;
  }
  
  // Substract gallons of fuel from the tank as we ride the car.
  public function ride($float)
  {
    $miles = $float;
    $gallons = $miles/50;
    $this-> tank -= ($gallons);
 
    return $this;
  }
}
Now, we can create an object from the Car class with the name of $bmw and find out the number of gallons of fuel left in our car's tank after we have filled the tank with 10 gallons of fuel and driven 40 miles.
// Create a new object from the Car class.
$bmw = new Car();
 
// Add 10 gallons of fuel, then ride 40 miles, 
// and get the number of gallons in the tank. 
$tank = $bmw -> fill(10) -> ride(40) -> tank;
 
// Print the results to the screen.
echo "The number of gallons left in the tank: " . $tank . " gal.";
Result:
The number of gallons left in the tank: 9.2 gal.


Access modifiers: public vs. private

In the previous tutorials, we used the public access modifier in front of the methods and properties in our classes without any explanation. The public access modifier is only one of several modifiers that we use. In this tutorial, we will learn about another modifier called the private access modifier.
While the public access modifier allows a code from outside or inside the class to access the class's methods and properties, the private modifier prevents access to a class's methods or properties from any code that is outside the class.
You'll learn   
·         How to use the public access modifier?
·         How to use the privateaccess modifier?
·         How to access a private property?
·         Why do we need access modifiers?

The public access modifier

The following example should already be familiar to you. In the example, the class’s property and method are defined as public, so the code outside the class can directly interact with them.
<?php
 
class Car {
 
  // public methods and properties.
  public $model;    
 
  public function getModel()
  {
    return "The car model is " . $this -> model;
  }
}
 
$mercedes = new Car();
//Here we access a property from outside the class
$mercedes -> model = "Mercedes";
//Here we access a method from outside the class
echo $mercedes -> getModel();
Result:
The car model is Mercedes

The private access modifier

We can prevent access to the properties and methods inside our classes if we define them with the private access modifier instead of the public access modifier.
In the following example, we define the property $model as private, and when we try to set its value from outside the class, we encounter a fatal error.
<?php
 
class Car {
 
  //private
  private $model;
    
  public function getModel()
  {
    return "The car model is " . $this -> model;
  }
}
 
$mercedes = new Car();
 
// We try to access a private property from outside the class.
$mercedes -> model = "Mercedes benz";
echo $mercedes -> getModel();
 
?>
Result:
Fatal error: Cannot access private property Car::$model

How to access a private property?

We saw that we have no access to private properties from outside the class, but we still have to somehow set and get the properties’ values. In order to interact with private properties, we use public methods because they can interact with both the code outside of the class’s scope as well as the code inside the class. The public methods that can interact in this manner are commonly divided into two kinds of methods:
Setters that set the values of the private properties.
Getters that get the values of the private properties.
In the following example, we will see that we can get and set the value of a private property, $carModel, through the use of setter and getter methods. We will use the setModel() method in order to set the value of the car model, and the getModel() method to get the value of the property.
<?php
 
class Car {
 
  //the private access modifier denies access to the method from outside the class’s scope
  private $model;
 
  //the public access modifier allows the access to the method from outside the class
  public function setModel($model)
  {
    $this -> model = $model;
  }
  
  public function getModel()
  {
    return "The car model is  " . $this -> model;
  }
}
 
$mercedes = new Car();
//Sets the car’s model
$mercedes -> setModel("Mercedes benz");
//Gets the car’s model
echo $mercedes -> getModel();
 
?>
Result:
The car model is Mercedes benz

Why do we need access modifiers?

We need access modifiers in order to limit the modifications that code from outside the classes can do to the classes' methods and properties. Once we define a property or method as private, only methods that are within the class are allowed to approach it. So, in order to interact with private methods and properties, we need to provide public methods. Inside these methods, we can put logic that can validate and restrict data that comes from outside the class.
In our example, we can validate that only certain car models can make their way, and be assigned to the private $modelproperty, by defining the allowed alternatives for models in the public setModel() method. For this purpose, we define inside the setModel() method an array of allowed car models, and check that only these models are assigned to the $model property.
<?php
 
class Car {
 
  //the private access modifier denies access to the method from outside the class’s scope
  private $model;
 
  //the public access modifier allows the access to the method from outside the class
  public function setModel($model)
  {
    //validate that only certain car models are assigned to the $carModel property
    $allowedModels = array("Mercedes benz","BMW");
 
    if(in_array($model,$allowedModels))
    {
      $this -> model = $model;
    }
    else
    {
      $this -> model = "not in our list of models.";
    }
  }
  
  public function getModel()
  {
    return "The car model is  " . $this -> model;
  }
}
 
 
$mercedes = new Car();
//Sets the car’s model
$mercedes -> setModel("Mercedes benz");
//Gets the car’s model
echo $mercedes -> getModel();
 
?>



Magic methods and constants unveiled

Object Oriented PHP offers several magic methods and constants that enable a lot of programming with very little code, but which suffer from a few disadvantages like a slight reduction in the performance time as well as in the level of code clarity.
There is much dispute about the use of magic methods, so in this tutorial we explain the parts of the field which are widely agreed, but ignore the parts in dispute.
You'll learn   
·         About the __construct()magic method.
·         How to write a constructor method without risking an error?
·         How to use magic constants?

The __construct() magic method

The names of magic methods always start with two underscores, and the __construct() magic method is no exception. We use __construct() in order to do something as soon as we create an object out of a class. A method of this kind is called a constructor. Usually we use the constructor to set a value to a property.
In our simple example, we want to set the value of the $model property as soon as we create the object, so we add a constructor inside the class that sets the value of the $model property.
class Car{
  private $model;
 
  // A constructor method.
  public function __construct($model)
  {
    $this -> model = $model;
  }
}
In order to use the constructor, we have to pass an argument to the class with the name of the model as soon as we create the object, but if we try to create a new object without assigning the value that the constructor needs, we will encounter an error.
$car1 = new Car();
Result:
Warning: Missing argument 1 for Car::__construct()
In order to avoid such an error, we have to assign a value to the constructor. Thus, for the sake of example, we assign the value "Mercedes" to the constructor by writing it within the brackets of the newly created object.
$car1 = new Car("Mercedes");
Now, let’s add the method getCarModel() in order to echo the car model from the object that we have just created.
class Car {
  private $model;
  
  //__construct
  public function __construct ($model)
  {
    $this -> model = $model;
  }
   
  public function getCarModel()
  {
    return ' The car model is: ' . $this -> model;
  }
}
  
//We pass the value of the variable once we create the object
$car1 = new Car("Mercedes");
  
echo $car1 -> getCarModel();
Result:
The car model is: Mercedes.

How to write a constructor method without risking an error?

When we try to create an object that has a constructor method, we run the risk of our code breaking if we don’t pass a value to the constructor. In order to avoid this risk, we can define a default value for the properties that we would like to set through the constructor. The default value may be the most reasonable choice for the property, zero, an empty string, or even a null.
If we use a null as the default value, we can use a condition to assess if a value was passed and then, only in that case, assign the value to the property.
In the example below, we give a default value of null to the $model property and, only if a value is passed to the constructor, we assign this value to the property. In any other case, the $model property has a default value of "N/A"string.
class Car {
  // The $model property has a default value of "N/A"
  private $model = "N/A";
  
  // We don’t have to assign a value to the $model property
  //since it already has a default value
  public function __construct($model = null)
  {
    // Only if the model value is passed it will be assigned
    if($model) 
    { 
      $this -> model = $model;
    }
  }
   
  public function getCarModel()
  {
    return ' The car model is: ' . $this -> model;
  }
}
  
//We create the new Car object without passing a value to the model
$car1 = new Car();
  
echo $car1 -> getCarModel();
Even though we created the object without passing a value to the model property, we didn't cause an error because the model property in the constructor has a default value of null.
Result:
The car model is: N/A
On the other hand, let’s see what happens when we define the model once we create the object. In the example, we assign the value "Merceds" to the $model property as soon as we create the object.
class Car {
  private $model = '';
 
  //__construct
  public function __construct($model = null)
  {
    if($model) 
    { 
      $this -> model = $model;
    }
  }
  
  public function getCarModel()
  {
    return ' The car model is: ' . $this -> model;
  }
}
 
//We create the new Car object with the value of the model
$car1 = new Car('Mercedes');
 
echo $car1 -> getCarModel();
Result:
The car model is: Mercedes

Magic constants

In addition to magic methods, the PHP language offers several magic constants.
For example, we may use the magic constant __CLASS__ (magic constants are written in uppercase letters and prefixed and suffixed with two underlines) in order to get the name of the class in which it resides.
Let’s take a look at the following example in which we use the __CLASS__ magic constant in the getCarModel()method to get the class's name:
class Car {
  private $model = '';
  
  //__construct
  public function __construct($model = null)
  {
    if($model) 
    { 
      $this -> model = $model;
    }
  }
   
  public function getCarModel()
  {
    //We use the __CLASS__ magic constant in order to get the class name
  
    return " The <b>" . __CLASS__ . "</b> model is: " . $this -> model;
  }
}
  
$car1 = new Car('Mercedes');
  
echo $car1 -> getCarModel();
Result:
TheCarmodel is: Mercedes
Other magic constants that may be of help are:
__LINE__ to get the line number in which the constant is used.
__FILE__ to get the full path or the filename in which the constant is used.
__METHOD__ to get the name of the method in which the constant is used.




Inheritance in object-oriented PHP

One of the main advantages of object-oriented programming is the ability to reduce code duplication with inheritance. Code duplication occurs when a programmer writes the same code more than once, a problem that inheritance strives to solve. In inheritance, we have a parent class with its own methods and properties, and a child class (or classes) that can use the code from the parent. By using inheritance, we can create a reusable piece of code that we write only once in the parent class, and use again as much as we need in the child classes.
You'll learn   
·         How can a class inherit the code of another class?
·         How can a child class have its own methods and properties?
·         About the protected access control modifier.
·         How to override the parent’s properties and methods in the child class?

How can a class inherit the code of another class?

Inheritance allows us to write the code only once in the parent, and then use the code in both the parent and the child classes.
In order to declare that one class inherits the code from another class, we use the extends keyword. Let's see the general case:
class Parent {
  // The parent’s class code
}
 
class Child extends Parent {
  // The  child can use the parent's class code
}
The child class can make use of all the non-private methods and properties that it inherits from the parent class. This allows us to write the code only once in the parent, and then use it in both the parent and the child classes.
In the example given below, the SportsCar class inherits the Car class, so it has access to all of the Car’s methods and properties that are not private. This allows us to write the setModel() and hello() public methods only once in the parent, and then use these methods in both the parent and the child classes.
//The parent class
class Car {
  // Private property inside the class
  private $model;
 
  //Public setter method
  public function setModel($model)
  {
    $this -> model = $model;
  }
 
  public function hello()
  {
    return "beep! I am a <i>" . $this -> model . "</i><br />";
  }
}
 
 
//The child class inherits the code from the parent class
class SportsCar extends Car {
  //No code in the child class
}
 
 
//Create an instance from the child class
$sportsCar1 = new SportsCar();
  
// Set the value of the class’ property.
// For this aim, we use a method that we created in the parent
$sportsCar1 -> setModel('Mercedes Benz');
  
//Use another method that the child class inherited from the parent class
echo $sportsCar1 -> hello();
Result:
beep! I am a Mercedes Benz

How can a child class have its own methods and properties?

Just as a child class can use the properties and methods of its parent class, it can have properties and methods of its own as well. However, while a child class can use the code it inherited from the parent, the parent class is not allowed to use the child class’s code.
In the example given below, we will add to the child class some code of its own by adding the $style property as well as the driveItWithStyle() method:
// The parent class has its properties and methods
class Car {
  
  //A private property or method can be used only by the parent.
  private $model;
  
  // Public methods and properties can be used by both the parent and the child classes.
  public function setModel($model)
  {
    $this -> model = $model;
  }
   
  public function getModel()
  {
    return $this -> model;
  }
}
 
  
//The child class can use the code it inherited from the parent class, 
// and it can also have its own code 
class SportsCar extends Car{
 
  private $style = 'fast and furious';
 
  public function driveItWithStyle()
  {
    return 'Drive a '  . $this -> getModel() . ' <i>' . $this -> style . '</i>';
  }
}
 
 
//create an instance from the child class
$sportsCar1 = new SportsCar();
   
// Use a method that the child class inherited from the parent class
$sportsCar1 -> setModel('Ferrari');
  
// Use a method that was added to the child class
echo $sportsCar1 -> driveItWithStyle();
Result:
Drive a Ferrari fast and furious.

The protected access control modifier

When we declare a property or a method as protected, we can approach it from both the parent and the child classes.
In a previous tutorial, we learned that we can use the public access modifier to allow access to a class’s methods and properties from both inside and outside the class. We also learned that those methods and properties that are private can only be used from inside the class.
In this tutorial, we will learn about a third modifier - the protected modifier, which allows code usage from both inside the class and from its child classes.
The first example demonstrates what might happen when we declare the $model property in the parent as private, but still try to access it from its child class.
What do you think might happen when we try to call a private method or property from outside the class?
Here is the code:
// The parent class
class Car {
  //The $model property is private, thus it can be accessed 
  // only from inside the class
  private $model;
  
  //Public setter method
  public function setModel($model)
  {
    $this -> model = $model;
  }
}
  
   
// The child class
class SportsCar extends Car{
  //Tries to get a private property that belongs to the parent
  public function hello()
  {
    return "beep! I am a <i>" . $this -> model . "</i><br />";
  }
}
   
//Create an instance from the child class
$sportsCar1 = new SportsCar();
  
//Set the class model name
$sportsCar1 -> setModel('Mercedes Benz');
   
//Get the class model name
echo $sportsCar1 -> hello();
Result:
Notice: Undefined property: SportsCar::$model
We get an error because the hello() method in the child class is trying to approach a private property, $model, that belongs to the parent class.
We can fix the problem by declaring the $model property in the parent as protected, instead of private, because when we declare a property or a method as protected, we can approach it from both the parent and the child classes.
// The parent class
class Car {
  //The $model property is now protected, so it can be accessed 
  // from within the class and its child classes
  protected $model;
   
  //Public setter method
  public function setModel($model)
  {
    $this -> model = $model;
  }
}
  
// The child class
class SportsCar extends Car {
  //Has no problem to get a protected property that belongs to the parent
  public function hello()
  {
    return "beep! I am a <i>" . $this -> model . "</i><br />";
  }
}
  
//Create an instance from the child class
$sportsCar1 = new SportsCar();
  
//Set the class model name
$sportsCar1 -> setModel('Mercedes Benz');
  
//Get the class model name
echo $sportsCar1 -> hello();
Result:
beep! I am a Mercedes Benz
Now it works, because we can access a protected code that belongs to a parent from a child class.

How to override the parent’s properties and methods in the child class?

In the same way that the child class can have its own properties and methods, it can override the properties and methods of the parent class. When we override the class’s properties and methods, we rewrite a method or property that exists in the parent again in the child, but assign to it a different value or code.
In the example given below, we create a hello() method in the parent class that returns the string "beep" and override it in the child class with a method by the same name that returns a different string, "Halllo".
Here is the code:
// The parent class has hello method that returns "beep".
class Car {
  public function hello()
  {
    return "beep";
  }
}
 
//The child class has hello method that returns "Halllo"
class SportsCar extends Car {
  public function hello()
  {
    return "Hallo";
  }
}
    
//Create a new object
$sportsCar1 = new SportsCar();
  
//Get the result of the hello method
echo $sportsCar1 -> hello();
Result:
Halllo
The result reflects the fact that the hello() method from the parent class was overridden by the child method with the same name.

How to prevent the child class from overriding the parent’s methods?

In order to prevent the method in the child class from overriding the parent’s methods, we can prefix the method in the parent with the final keyword.
In the example given below, we declare the hello() method in the parent as final, but still try to override it in the child class. What do you think might happen if we try to override a method that was declared as final?
// The parent class has hello method that returns "beep".
 
class Car {
  final public function hello()
  {
    return "beep";
  }
}
 
//The child class has hello method that tries to override the hello method in the parent
class SportsCar extends Car {
  public function hello()
  {
    return "Hallo";
  }
}
  
 
//Create a new object
$sportsCar1 = new SportsCar();
  
//Get the result of the hello method
echo $sportsCar1 -> hello();
Result:
Fatal error: Cannot override final method Car::hello()
Since we declared the hello method as final in the parent, we cannot override the method in the child class.



Abstract classes and methods

We use abstract classes when we want to commit the programmer (either oneself or someone else) to write a certain class method, but we are only sure about the name of the method, and not the details of how it should be written. To take an example, circles, rectangles, octagons, etc. may all look different, but are all 2D shapes nonetheless, and thus all possess the traits of area and circumference. So, it makes perfect sense to group the code that they have in common into one parent class. In this parent class, we would have the two properties of area and circumference, and we might even consider adding a method that calculates the area (which might be problematic since different shapes require different calculations). In these kinds of cases, when we need to commit the child classes to certain methods that they inherit from the parent class but we cannot commit about the code that should be used in the methods, we use abstract classes.
We use abstract classes and methods when we need to commit the child classes to certain methods that they inherit from the parent class but we cannot commit about the code that should be written inside the methods.
An abstract class is a class that has at least one abstract method. Abstract methods can only have names and arguments, and no other code. Thus, we cannot create objects out of abstract classes. Instead, we need to create child classes that add the code into the bodies of the methods, and use these child classes to create objects.
You'll learn   
·         How to declare classes and methods as abstract?
·         Can we have non abstract methods inside an abstract class?
·         How to create child classes from an abstract class?

How to declare classes and methods as abstract?

In order to declare a class as abstract, we need to prefix the name of the class with the abstract keyword.
See the following example:
 1abstract class Car { }
We put the abstract methods that are also declared with the abstract keyword within the abstract class. Abstract methods inside an abstract class don't have a body, only a name and parameters inside parentheses.
In the example given below, we create a public abstract method, calcNumMilesOnFullTank(), that is the skeleton for methods that we will create in the child classes. Once created, these methods will return the number of miles a car can be driven on a tank of gas.
// Abstract classes are declared with the abstract keyword, and contain abstract methods.
abstract class Car {
  abstract public function calcNumMilesOnFullTank();
}
It is important to know that once we have an abstract method in a class, the class must also be abstract.

Can we have non abstract methods inside an abstract class?

An abstract class can have non abstract methods. In fact, it can even have properties, and properties couldn't be abstract.
Let's add to our example the protected property, $tankVolume, and public method with the name of setTankVolume().
abstract class Car {
  // Abstract classes can have properties
  protected $tankVolume;
 
  // Abstract classes can have non abstract methods
  public function setTankVolume($volume)
  {
    $this -> tankVolume = $volume;
  }
 
  // Abstract method
  abstract public function calcNumMilesOnFullTank();
}

How to create child classes from an abstract class?

Since we cannot create objects from abstract classes, we need to create child classes that inherit the abstract class code. Child classes of abstract classes are formed with the help of the extends keyword, like any other child class. They are different in that they have to add the bodies to the abstract methods.
The child classes that inherit from abstract classes must add bodies to the abstract methods.
Let's create a child class with the name of Honda, and define in it the abstract method that it inherited from the parent, calcNumMilesOnFullTank().
class Honda extends Car {
  // Since we inherited abstract method, we need to define it in the child class, 
  // by adding code to the method's body.
  public function calcNumMilesOnFullTank()
  {
    $miles = $this -> tankVolume*30;
    return $miles;
  }
}
We can create another child class from the Car abstract class and call it Toyota, and here again define the abstract method calcNumMilesOnFullTank() with a slight change in the calculation. We will also add to the child class its own method with the name of getColor() that returns the string "beige".
 class Toyota extends Car {
  // Since we inherited abstract method, we need to define it in the child class, 
  // by adding code to the method's body.
  public function calcNumMilesOnFullTank()
  {
    return $miles = $this -> tankVolume*33;
  }
 
  public function getColor()
  {
    return "beige";
  }
}
Let's create a new object, $toyota1, with volume of 10 Gallons, and let it return the number of miles on full tank and the car's color.
$toyota1 = new Toyota();
$toyota1 -> setTankVolume(10);
echo $toyota1 -> calcNumMilesOnFullTank();//330
echo $toyota1 -> getColor();//beige




Interfaces - the next level of abstraction

Interfaces resemble abstract classes in that they include abstract methods that the programmer must define in the classes that inherit from the interface. In this way, interfaces contribute to code organization because they commit the child classes to abstract methods that they should implement. The use of interfaces becomes very helpful when we work in a team of programmers and want to ensure that all the programmers write the methods that they should work on, or even in the case of a single programmer that wants to commit himself to write certain methods in the child classes.
An interface commits its child classes to abstract methods that they should implement.
You'll learn   
·         How to declare and implement an interface?
·         Can we implement more than one interface in the same class?
·         What are the differences between abstract classes and interfaces?

How to declare and implement an interface?

We declare an interface with the interface keyword and, the class that inherits from an interface with the implementskeyword. Let's see the general case:
interface interfaceName { 
  // abstract methods
}
 
class Child implements interfaceName {
  // defines the interface methods and may have its own code
}
In the simple example given below, we will create an interface for the classes that handle cars, which commits all its child classes to setModel() and getModel() methods.
interface Car { 
  public function setModel($name);
  
  public function getModel();
}
Interfaces, like abstract classes, include abstract methods and constants. However, unlike abstract classes, interfaces can have only public methods, and cannot have variables.
The classes that implement the interfaces must define all the methods that they inherit from the interfaces, including all the parameters. So, in our concrete class with the name of miniCar, we add the code to all the abstract methods.
class miniCar implements Car {
  private $model; 
   
  public function setModel($name)
  { 
    $this -> model = $name; 
  }
  
  public function getModel()
  {
    return $this -> model; 
  }
}

Can we implement more than one interface in the same class?

We can implement a number of interfaces in the same class.
We can implement a number of interfaces in the same class, and so circumvent the law that prohibits the inheritance from more than one parent class. In order to demonstrate multiple inheritance from different interfaces, we create another interface, Vehicle, that commits the classes that implement it to a boolean $hasWheels property.
interface Vehicle {
  public function setHasWheels($bool); 
 
  public function getHasWheels();
}
Now, our child class can implement the two interfaces.
class miniCar implements Car, Vehicle {
  private $model; 
  private $hasWheels; 
  
  public function setModel($name)
  { 
    $this -> model = $name; 
  }
  
  public function getModel()
  {
    return $this -> model; 
  }
  
  public function setHasWheels($bool)
  { 
    $this -> hasWheels = $bool; 
  }
  
  public function getHasWheels()
  {
  return ($this -> hasWheels)? "has wheels" : "no wheels";
  }
}

What are the differences between abstract classes and interfaces?

We saw that abstract classes and interfaces are similar in that they provide abstract methods that must be implemented in the child classes. However, they still have the following differences:
·         Interfaces can include abstract methods and constants, but cannot contain concrete methods and variables.
·         All the methods in the interface must be in the public visibility scope.
·         A class can implement more than one interface, while it can inherit from only one abstract class.
Let's summarize these differences in the following table:
interface
abstract class
the code
- abstract methods
- constants
- abstract methods
- constants
- concrete methods
- concrete variables
access modifiers
- public
- public
- protected
- private
etc.
number of parents
The same class can implement more than 1 interface
The child class can inherit only from 1 abstract class



Polymorphism in PHP

In this tutorial, we are going to learn about Polymorphism (Greek for "many forms") a naming convention that can help us write code which is much more coherent and easy to use. According to the Polymorphismprinciple, methods in different classes that do similar things should have the same name.
According to the Polymorphism principle, methods in different classes that do similar things should have the same name.
A prime example is of classes that represent geometric shapes (such as rectangles, circles and octagons) that are different from each other in the number of ribs and in the formula that calculates their area, but they all have in common an area that can be calculated by a method. The polymorphism principle says that, in this case, all the methods that calculate the area (and it doesn't matter for which shape or class) would have the same name.
For example, we can call the method that calculates the area calcArea() and decide that we put, in each class that represents a shape, a method with this name that calculates the area according to the shape. Now, whenever we would want to calculate the area for the different shapes, we would call a method with the name of calcArea()without having to pay too much attention to the technicalities of how to actually calculate the area for the different shapes. The only thing that we would need to know is the name of the method that calculates the area.
Tutorials list   
·         >> See them all
·         1. Classes and objects
·         2. The $this keyword
·         4. Public vs. Private
·         5. Magic methods and Constants
·         6. Inheritance in PHP
·         7. Abstract classes & methods
·         8. Interfaces
·         9. Polymorphism
·         10. Type hinting
·         12. The static keyword

How to implement the polymorphism principle?

In order to implement the polymorphism principle, we can choose between abstract classes and interfaces.
In order to ensure that the classes do implement the polymorphism principle, we can choose between one of the two options of either abstract classes or interfaces.
In the example given below, the interface with the name of Shape commits all the classes that implement it to define an abstract method with the name of calcArea().
interface Shape {
  public function calcArea();
}
In accordance, the Circle class implements the interface by putting into the calcArea() method the formula that calculates the area of circles.
class Circle implements Shape {
  private $radius;
   
  public function __construct($radius)
  {
    $this -> radius = $radius;
  }
  
  // calcArea calculates the area of circles 
  public function calcArea()
  {
    return $this -> radius * $this -> radius * pi();
  }
}
The rectangle class also implements the Shape interface but defines the method calcArea() with a calculation formula that is suitable for rectangles:
class Rectangle implements Shape {
  private $width;
  private $height;
   
  public function __construct($width, $height)
  {
    $this -> width = $width;
    $this -> height = $height;
  }
  
  // calcArea calculates the area of rectangles   
  public function calcArea()
  {
    return $this -> width * $this -> height;
  }
}
Now, we can create objects from the concrete classes:
$circ = new Circle(3);
$rect = new Rectangle(3,4);
We can be sure that all of the objects calculate the area with the method that has the name of calcArea(), whether it is a rectangle object or a circle object (or any other shape), as long as they implement the Shape interface.
Now, we can use the calcArea() methods to calculate the area of the shapes:
echo $circ -> calcArea();
echo $rect -> calcArea();
Result:
28.274333882308
12




Type hinting

With Type hinting we can specify the expected data type (arrays, objects, interface, etc.) for an argument in a function declaration. This practice can be most advantageous because it results in better code organization and improved error messages.
This tutorial will start by explaining the subject of type hinting for arrays and objects which is supported in both PHP5 as well as PHP7.
It will also explain the subject of type hinting for basic data types (integers, floats, strings, and booleans) which is only supported in PHP7.
You'll learn   
·         How to do array type hinting?
·         How to do object type hinting?
·         PHP support for basic data types

How to do array type hinting?

When we would like to force a function to get only arguments of the type array, we can put the keyword array in front of the argument name, with the following syntax:
function functionName (array $argumentName)
{
  //code
}
In the following example, the calcNumMilesOnFullTank() function calculates the number of miles a car can be driven on a full tank of gas by using the tank volume as well as the number of miles per gallon (mpg). This function accepts only array as an argument, as we can see from the fact that the argument name is preceded by the array keyword.
// The function can only get array as an argument.
function calcNumMilesOnFullTank(array $models)
{
  foreach($models as $item)
  {
    echo $carModel = $item[0];
    echo " : ";
    echo $numberOfMiles = $item[1] * $item[2];
    echo "<br />";
   }
}
First, let's try to pass to the function an argument which is not an array to see what might happen in such a case:
calcNumMilesOnFullTank("Toyota");
Result:
Catchable fatal error: Argument 1 passed to calcNumMilesOnFullTank() must be of the type array, string given
This error is a precise description of what went wrong with our code. From it, we can understand that the function expected an array variable, and not a string.
Let's rewrite the code and pass to the function an array with the expected items, including the model names, the tank volumes, and the mpg (miles per gallon).
$models = array(
  array('Toyota', 12, 44),
  array('BMW', 13, 41)
);
 
calcNumMilesOnFullTank($models);
Result:
Toyota : 528
BMW : 533
Now it's working because we passed to the function the array that it expected to get.

How to do object type hinting?

Type hinting can also be used to force a function to get an argument of type Object. For this purpose, we put the name of the class in front of the argument name in the function.
In the following example, the class's constructor can only get objects that were created from the Driver class. We ensure this by putting the word Driver in front of the argument name in the constructor.
class Car {
  protected $driver;
       
  // The constructor can only get Driver objects as arguments.
  public function __construct(Driver $driver)
  {
    $this -> driver = $driver;
  }
}
 
 
class Driver {}
 
 
$driver1 = new Driver();
$car1    = new Car($driver1);

Does PHP support type hinting to basic data types?

It depends.
Whereas PHP5 doesn’t allow type hinting for basic data types (integers, floats, strings and booleans), PHP7 does support scalar type hinting.
PHP5 does not support type hinting to basic data types like integers, booleans or strings. So, when we need to validate that an argument belongs to a basic data type, we can use one of PHP’s “is_” family functions. For example:
·         is_bool - to find out whether a variable is a boolean (true or false).
·         is_int - to find out whether a variable is an integer.
·         is_float - to find out whether a variable is a float (3.14, 1.2e3 or 3E-10).
·         is_null - to find out whether a variable is null.
·         is_string - to find out whether a variable is a string.
On the other hand, PHP7 does support scalar type hinting. The supported types are: integers, floats, strings, and booleans.
The following code example can only work in PHP7.
class car {
  protected $model;
  protected $hasSunRoof;
  protected $numberOfDoors;
  protected $price;
 
  // string type hinting
  public function setModel(string $model)
  {
    $this->model = $model;
  }
 
  // boolean type hinting
  public function setHasSunRoof(bool $value)
  {
    $this->hasSunRoof = $value;
  }
 
  // integer type hinting
  public function setNumberOfDoors(int $value)
  {
    $this->numberOfDoors = $value;
  }
 
  // float type hinting
  public function setPrice(float $value)
  {
    $this->price = $value;
  }        
}


Type hinting for interfaces

In the previous tutorial, we learned that type hinting contributes to code organization and improves error messages. In this tutorial, we will learn how to implement type hinting for interfaces.
In the first part of the chapter we will see that the use of type hinting for objects is not always sufficient, and in the second part we will learn how to fix the problem by the use of type hinting for interfaces.
You'll learn   
·         Why type hinting for objects may not be sufficient?
·         How to do type hinting for interfaces?

Why type hinting for objects may not be sufficient?

We will base our tutorial on the following imaginary scenario: A manager in a car rental company that rents only BMWs hired a programmer to write a program that calculates the price for a full tank of gas for each and every car that the company owns. In accordance with these demands, the programmer writes a class to which he decides to call Bmw that holds the code for the task. This class has the data about the BMWs including the license plate number, the car model and, most importantly, it has a method that calculates the volume of the fuel tank.
The function that calculates the volume is called calcTankVolume. This method calculates the tank volume by multiplying the base area (the square of the base ribs' length) and the height. The height, as well as the length of the base ribs and the license plate number, is introduced to the class through the constructor.
class Bmw {
 
  protected $model;
  protected $rib;
  protected $height;
   
  // The properties are introduced to the class through the constructor
  public function __construct($model, $rib, $height)
  {
    $this -> model = $model;
    $this -> rib = $rib;
    $this -> height = $height;
  }
 
  // Calculate the tank volume for rectangular tanks
  public function calcTankVolume()
  {
    return $this -> rib * $this -> rib * $this -> height;
  } 
}
Outside of the class, the programmer writes a function to calculate the price for a full tank of gas by multiplying the tank volume (gallons) and the price per gallon. However, since he doesn't want the function to get any argument other than those that belong to the Bmw class, he uses type hinting:
// Type hinting ensures that the function gets only Bmw objects as arguments
function calcTankPrice(Bmw $bmw, $pricePerGalon)
{
    return $bmw -> calcTankVolume() * 0.0043290 * $pricePerGalon . "$";
}
Now, he can easily calculate how much a full tank of gas costs for BMWs. For example, for a car with the license plate number of '62182791', a rib length of 14″ a height of 21″, and using gas priced at 3 dollars per gallon.
$bmw1 = new Bmw('62182791', 14, 21); 
echo calcTankPrice($bmw1, 3) ;
Result:
53.454492$

How to do type hinting for interfaces?

After a short time, the manager decides to introduce to his fleet of cars a brand new Mercedes, but the problem is that the calcTankPrice() function can only perform calculations for BMWs. It turns out that, while BMWs have a rectangular shaped gas tank, Mercedes have a cylindrical shaped gas tank. So, our programmer is summoned once again to write another class that can handle this new task at hand. To this end, our programmer now writes the following class with the name of Mercedes that can calculate the tank volume for cylindrical shaped tanks.
class Mercedes {
  protected $model;
  protected $radius;
  protected $height;
   
  public function __construct($model, $radius, $height)
  {
    $this -> model = $model;
    $this -> radius = $radius;
    $this -> height = $height;
  }
   
  // Calculates the volume of cylinder
  public function calcTankVolume()
  {
    return $this -> radius * $this -> radius * pi() * $this -> height;
  }
}
When our programmer completed the task of writing the Mercedes class, he tried to calculate the price of a full tank of gas for a Mercedes.
$mercedes1 = new Mercedes('12189796', 7, 28); 
echo calcTankPrice($mercedes1, 3);
However, the result wasn't quite what he had expected:
Result:
Catchable fatal error: Argument 1 passed to calcTankPrice() must be an instance of Bmw, instance of Mercedes given
This error message is the result of not passing the right object to the function, since he tried to pass a Mercedes object to the calcTankVolume() function whereas the function can only accept objects that belong to the Bmw class.
First, our programmer attempted to solve the problem by not using any type hinting, but then he understood that a better solution would be the use of type hinting for interfaces. Here I use interface in its wider meaning that includes both abstract classes as well as real interfaces.
Here I use interface in its wider meaning that includes both abstract classes as well as real interfaces.
So, first he created an abstract class with the name of Car that both the Bmw and the Mercedes (and, in fact, any other car model) can inherit from.
abstract class Car {
  protected $model;
  protected $height;
     
  abstract public function calcTankVolume();
}
Then he re-factored the Bmw and Mercedes classes so that they inherit from the Car class:
class Bmw extends Car {
 
  protected $rib;
  
  public function __construct($model, $rib, $height)
  {
    $this -> model = $model;
    $this -> rib = $rib;
    $this -> height = $height;
  }
   
  // Calculates a rectangular tank volume
  public function calcTankVolume()
  {
    return $this -> rib * $this -> rib * $this -> height;
  } 
}
 
 
class Mercedes extends Car {
  protected $radius;
   
  public function __construct($model, $radius, $height)
  {
    $this ->model = $model;
    $this -> radius = $radius;
    $this -> height = $height;
  }
 
  
  // Calculates the volume of cylinders
  public function calcTankVolume()
  {
    return $this -> radius * $this -> radius * pi() * $this -> height;
  }
}
The following diagram can help us to better understand the relation between the Car interface and the concrete classes (Bmw and Mercedes) that implement the interface for different gas tank shapes:
The Car interface and the concrete classes that implement it
Since both the classes inherit from the same interface, he could comfortably type hint the function calcTankPrice()with the Car interface, so that the function can get any object as long as it belongs to this interface.
// Type hinting ensures that the function gets only objects 
// that belong to the Car interface
function calcTankPrice(Car $car, $pricePerGalon)
{
  echo $car -> calcTankVolume() * 0.0043290 * $pricePerGalon . "$";
}
Now, let's see the result when we try to use the function calcTankPrice() on both a Bmw and a Mercedes objects:
$bmw1 = new Bmw('62182791', 14, 21); 
echo calcTankPrice($bmw1, 3);
 
$mercedes1 = new Mercedes('12189796', 7, 28); 
echo calcTankPrice($mercedes1, 3);
Result:
53.454492$
55.977413122858$
Whenever we need to do type hinting to more than one related classes, we should be using interface type hinting.
THE MESSAGE TO TAKE HOME IS:
The message to take home from this tutorial is that, whenever we need to do type hinting to more than one related classes, we should be using interface type hinting.
Programming to an interface makes the code much more flexible and ready for changes.
Another very important lesson that the above examples can teach us, is the importance of programming to an interface. When the programmer had made the calcTankPrice function dependent on the Bmw class, he restricted the class use to only one car type. But when he chose to make the function dependent on an interface he allowed the function to be used for any car type, and so made it much more flexible. From this we can conclude that programming to an interfacemakes the code much more flexible and ready for changes.




Static methods and properties

In certain cases, it is better to approach methods and properties of a class without the need to create an object out of the class. This can be achieved by defining the methods and properties of a class as static. Even though the use of static methods and properties is considered a bad practice, there are cases in which their use is quite handy and justified.
In certain cases, it is better to approach methods and properties of a class without the need to create an object out of the class.
We have already learned about the three access modifiers called publicprotected and private. This tutorial is devoted to the fourth modifier, static, that allows access to classes' properties and methods without the need to create objects out of the classes.
You'll learn   
·         How to define methods and properties as static?
·         How to approach the staticmethods from within the class?
·         When to use static properties and methods?
·         Why static should be used with caution?

How to define methods and properties as static?

In order to define methods and properties as static, we use the reserved keyword static. In the following example, the class Utilis has a static public property with the name of $numCars and so the variable name is preceded by both the static and the public keywords.
class Utilis {
  // static methods and properties are defined with the static keyword.
  static public $numCars = 0;
}

How to approach static methods and properties?

In order to approach static methods and properties we use the scope resolution operator (::). In the example given below, in order to work with the static property of $numCars, we use the following code:
// set the number of cars
Utilis::$numCars = 3;
 
// get the number of cars
echo Utilis::$numCars;
Result:
3
Pay attention to the use of the $ sign right after the scope resolution operator.

How to approach the static methods from within the class?

In the same manner that we used the $this keyword to approach the class's own properties and methods from within the class, we use the reserved keyword self to approach static methods and properties.
In the example given below, the method addToNumCars() gets and sets the number of cars from the static $numCarsproperty within the same class by using the self keyword.
class Utilis {
  static public $numCars = 0;
 
  static public function addToNumCars($int)
  {
    $int = (int)$int;
    self::$numCars += $int;
  }
}
Now, we can use the code we have written so far to set and get the number of cars.
echo Utilis::$numCars;
 
Utilis::addToNumCars(3);
echo Utilis::$numCars;
 
Utilis::addToNumCars(-1);
echo Utilis::$numCars;
Result:
0
3
2

When to use static properties and methods?

The main cases in which we consider the use of static methods and properties are when we need them as counters and for utility classes.
The use of static properties and methods is considered to be a bad practice. However, in some cases, the ability to use a property or a method without the need to create an object can be advantageous. The main cases in which we consider the use of static methods and properties are when we need them as counters and for utility classes.

Use case 1: as counters

We use static properties as counters since they are able to save the last value that has been assigned to them. For example, the method add1ToCars() adds 1 to the $numberOfCars property each time the method is called.
class Utilis {
  // Hold the number of cars.
  static public $numberOfCars = 0;
 
  // Add 1 to the number of cars each time the method is called.
  static public function add1ToCars()
  {
    self::$numberOfCars++;
  }
}
 
echo Utilis::$numberOfCars;
 
Utilis::add1ToCars();
echo Utilis::$numberOfCars;
 
Utilis::add1ToCars();
echo Utilis::$numberOfCars;
 
Utilis::add1ToCars();
echo Utilis::$numberOfCars;
Result:
0
1
2
3

Use case 2: for utility classes

It is very common to use static methods for utility classes. The sole purpose of utility classes is to provide services to the main classes. Utility methods can perform all kinds of tasks, such as: conversion between measurement systems (kilograms to pounds), data encryption, sanitation, and any other task that is not more than a service for the main classes in our application.
The example given below is of a static method with the name of redirect that redirects the user to the URL that we pass to it as an argument.
class Utilis {
  // The method uses PHP's header function to redirect the user.
  static public function redirect($url)
  {
    header("Location: $url");
    exit;
  }
}
In order to use the redirect() method, all we need to do is call it from the scope of the Utilis class without having the need to create an object. It's as simple as this:
 1Utilis::redirect("http://www.phpenthusiast.com");

Why static should be used with caution?

Whenever you use static, be sure to use it for utilities and not for convenience reasons.
If you are considering the use of static methods and properties because they are convenient and can be approached without the need to first create an object, please be cautious, because static methods suffer from the following two major disadvantages:
1.     You will have a hard time performing automated testing on classes that use static methods.
2.     Static methods and variables present globals to the code that can be approached from anywhere. This is something that we should try to avoid as much as possible.
So, whenever you use static, be sure to use it for utilities and not for convenience reasons.




No comments:

Post a Comment