PHP OOP
Tags: beginners, php
Published: 2021-10-26 07:30:03

OOP stands for Object-Oriented Programming. Object-oriented programming is about creating objects that contain both data and functions, this is different from Procedural programming which is about writing procedures or functions that perform operations on the data.

**NB:**You can test the code in this article at [One Compiler](https://onecompiler.com/php)
######Why OOP?
- OOP is faster and easier to execute
- OOP provides a clear structure for the programs
- OOP helps to keep the PHP code DRY "Don't Repeat Yourself", and 
  makes the code easier to maintain, modify and debug
- OOP makes it possible to create full reusable applications with 
  less code and shorter development time

######Classes & Objects
Classes and objects are the two main aspects of object-oriented programming.

For example

So, a class is a template for objects, and an object is an instance of a class.

When the individual objects are created, they inherit all the properties and behaviors from the class, but each object will have different values for the properties.

######Class
Let assume we have a class Person, a person has a name, age and gender.
To define a class, use curly braces.In a class, variables are called properties and functions are called methods!

```
<?php
class Person{ 
 //properties of the class
 public $name;
 public $age;
 public $gender;
 //methods of the class
 function setName($name){
   $this->name = $name;
 }
 function getName(){
   echo $this->name;
 }
 function setAge($age){
   $this->age = $age;
 }
 function getAge(){
   echo $this->age;
 }
 function setGender($gender){
   $this->gender = $gender;
 }
 function getGender(){
   echo $this->gender;
 }


}

$person = new Person();
$person->setName("Samuel");
$person->getName();
?>
```
######Objects
Classes are nothing without objects! We can create multiple objects from a class. Each object has all the properties and methods defined in the class, but they will have different property values.

Objects of a class is created using the `new` keyword.

```
<?php
$person1 = new Person()
$person1->setName('samuel')
echo "Name:" .$person1->getName()
?>
```

######The `$this` Keyword
The `$this` keyword refers to the current object, and is only available inside methods.

######PHP - `instanceof`
You can use the `instanceof` keyword to check if an object belongs to a specific class:
```
<?php
$person1= new Person();
var_dump($person1 instanceof Person);
?>
```

######The `__construct` Function

A `constructor` allows you to initialize an object's properties upon creation of the object.
If you create a `__construct()` function, PHP will automatically call this function when you create an object from a class.

```
<?php
class Person{ 
 //properties of the class
 public $name;
 public $age;
 public $gender;
 //methods of the class
function __construct($name,$age,$gender) {
    $this->name = $name;
    $this->age = $age;
    $this->gender = $gender;
}

 function getName(){
   return $this->name;
 }
 function getAge(){
   return $this->age;
 }
 function getGender(){
   return $this->gender;
 }
}

$person = new Person("Samuel", 18, "Male");
echo $person->getName();
echo "\n";
echo $person->getAge();
echo "\n";
echo $person->getGender();
?>

```
######The `__destruct` Function

A `destructor` is called when the object is destructed or the script is stopped or exited.
If you create a __destruct() function, PHP will automatically call this function at the end of the script.

```
<?php
class Person{ 
 //properties of the class
 public $agename;
 public $age;
 public $gender;
 //methods of the class
function __construct($name,$age,$gender) {
    $this->name = $name;
    $this->age = $age;
    $this->gender = $gender;
}
function __destruct() {
  echo "Hello {$this->name}, you are a {$this->gender} who is {$this->age} old.";
}


}

$person1 = new Person("Samuel", 18, "Male");

```
######Access Modifiers

Properties and methods can have access modifiers which control where they can be accessed.

There are three access modifiers:

`public` - the property or method can be accessed from everywhere. This is default
`protected` - the property or method can be accessed within the class and by classes derived from that class
`private` - the property or method can ONLY be accessed within the class

Check out the example below where we use the access modifiers on properties:
```
<?php
class Person{ 
 //properties of the class
 public $name;
 protected $age;
 private $gender;
}

$person = new Person();
$person->name = 'Samuel';//OK
echo $person->name;
$person1->age = 18;//Error
echo $person->age;
$person1->gender = 'Male';//Error
echo $person->gender;

```
Check out the example below where we use the access modifiers on the methods:

```
<?php
class Person{ 
 //properties of the class
 public $name;
 public $age;
 public $gender;
 //methods of the class
 function setName($name){
   $this->name = $name;
 }
 protected function setAge($age){
   $this->age = $age;
 }
 private function setGender($gender){
   $this->gender = $gender;
 }
}
$person= new Person();
$person->setName('Samuel'); // OK
echo $person->name;
$person->setAge(18); // ERROR
echo $person->age;
$person->setGender('Male'); // ERROR
echo $person->gender;
?>

```
######Inheritance

Inheritance is when a class derives from another class.

Except for private properties & methods the child class will inherit all public and protected properties and methods from the parent class. In addition, it can have its own properties and methods.

An inherited class is defined by using the `extends` keyword.
```
<?php
class Person{ 
 //properties of the class

 public $name;
 public $age;
 public $gender;

 //methods of the class
 public function __construct($name,$age,$gender){
   $this->name = $name;
   $this->age = $age;
   $this->gender = $gender;
 }
 public function personalDetails(){
   echo "My name is {$this->name}, i am {$this->age} old and i am a {$this->gender}";
 }
}

class Interview extends Person{
    public function askForDetails(){
       echo "What is your name, age and gender?";
    }
}

$answer = new Interview("Samuel",18,"Male");
$answer->askForDetails();
$answer->personalDetails();
?>

```
######Abstract Classes & Methods

For  Abstract Classes to exist there must be a `parent class` and a `child class` relationship. That means they can only exist in a situation a class inherits from another.

Abstract methods, in the child class have access to the both the public, protected and _construct properties.

Points to note:
- you have to declare an abstract method or class using the `abstract` keyword
-For abstract methods they must have the same name in the child class as in the parent class. They must have the same number of arguments, however a child method can have additional arguments.
- The child class method must be defined with the same or a less restricted access modifier. `Private` wont work.

Let us look at the following example:

```
<?php  
abstract class Person{
 public $name;

 public function __construct($name){
  $this->name= $name;
 }
 abstract function greet();
}
class Greeting extends Person{
   public function greet() {
      echo "Hello, {$this->name}";
   }
}

$person1 = new Greeting("Samuel");
$person1->greet();
```

Let us look at this other example where abstract method has argument:

```
<?php
abstract class Person{
 public $name;

 public function __construct($name){
  $this->name= $name;
 }
 abstract protected function greet($honor);
}
class Greeting extends Person{
   public function greet($honor) {
      echo "Hello, {$honor} {$this->name} ";
   }
}

$person1 = new Greeting("Samuel");
$person1->greet("Hon");
```
Let us look at this other example where the child abstract method has optional argument:

```
<?php
abstract class Person{
 public $name;

 public function __construct($name){
  $this->name= $name;
 }
 abstract protected function greet($honor);
}
class Greeting extends Person{
   public function greet($honor,$salutation ="Welcome",$location ="Jamrock ") {
      echo "Hello, {$honor} {$this->name} {$salutation} to {$location} ";
   }
}

$person1 = new Greeting("Samuel");
$person1->greet("Professor");
```
######Interfaces
Interfaces allow you to create code which specifies which methods a class must implement, without any of the methods having their contents defined. Interfaces can be used in different classes this is referred as **Polymorphism.**

Interfaces are almost like abstract classes , difference being:
- all methods must be public in an interface unlike in an abstract class where they can be `protected` or `public`
- interfaces are declared with the `interface` keyword
- classes can inherit from other classes but still use  interfaces unlike abstract classes

Its however important to note all interface methods are abstract without the `abstract` keyword
To use an interface, a class must use the `implements` keyword. See example below:

```
<?php
interface Vehicle{
  public function typeOfFuel();
}
class Lorry implements Vehicle{
  public function typeOfFuel(){
    echo "I use Diesel";
  }
}
class Sedan implements Vehicle{
  public function typeOfFuel(){
    echo "I use Petrol";
  }
}
class Hatchback implements Vehicle{
  public function typeOfFuel(){
    echo "I use electricity";
  }
}

$lorry = new Lorry();
$lorry->typeOfFuel();
echo "\n";
$sedan = new Sedan();
$sedan->typeOfFuel();
echo "\n";
$hatchBack = new Hatchback();
$hatchBack->typeOfFuel();
```
######Traits
PHP allows single inheritance only, A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies.A Trait is similar to a class, but only intended to group functionality in a fine-grained and consistent way.It can have all access modifiers.

**You may ask yourself why would we need `traits` while we have `Interfaces` ?**
The difference is interfaces only have abstract methods. A trait has methods that are abstract and also defined.

To declare a trait use the `trait` keyword.

```
<?php
trait Person{
  public function talk(){
    echo "Hello,call later ";
  }
  public function walk(){
    echo "I am driving";
  }

}

class Driver{
   use Person;
}

$driver = new Driver();
$driver->talk();
$driver->walk();
```
**Using Multiple Traits**
```
<?php
trait Model {
    public function carModel() {
        echo 'Volvo ';
    }
}

trait Year {
    public function manufactureYear() {
        echo '2014';
    }
}

class DefineVehicle {
    use Model, Year;
    public function DescribeVehicle() {
        echo 'The Vehicle type is:';
    }
}

$car = new DefineVehicle();
$car->DescribeVehicle();
$car->carModel();
$car->manufactureYear();

?>
?>
```
######Static Methods
Static methods can be called directly - without creating an instance of the class first.
Static methods are declared with the `static` keyword:
```
<?php
class greeting {
  public static function welcome() {
    echo "Hello World!";
  }
}
// Call static method
greeting::welcome();
?>
```
A static method can be accessed from a method in the same class using the self keyword and double colon (::):

```
<?php
class greeting {
  public static function welcome() {
    echo "Hello World!";
  }

  public function __construct() {
    self::welcome();
  }
}

new greeting();
?>
```
Static methods can also be called from methods in other classes. To do this, the static method should be public:
```
<?php
class greeting {
  public static function welcome() {
    echo "Hello World!";
  }
}

class SomeOtherClass {
  public function message() {
    greeting::welcome();
  }
}
?>
```
To call a static method from a child class, use the `parent` keyword inside the child class. Here, the static method can be public or protected.

```
<?php
class Name{
  protected static function getName() {
    return "Bazeng";
  }
}

class SayName extends Name {
  public $name;
  public function __construct() {
    $this->name= parent::getName();
  }
}

$name= new SayName;
echo $name ->name;
?>
```
######Static properties 
Static properties are declared with the static `keyword` they can be called directly - without creating an instance of a class.Example:
```
<?php
class Person{
   public static $name = "Bazeng";
 }
echo Person::$name;
```
To access a static property in a method in same class use `self`
```
<?php
class Person{
   public static $name = "Bazeng";
   public function sayName(){
     echo self::$name;
   }
 }
 
 $person = new Person();
 $person->sayName();

```
To access a static property in a method in a parent class use `parent`
```
<?php
class Person{
   public static $name = "Bazeng";

 }
class SayName extends Person{
   public function __construct(){
    echo parent::$name;
   }
} 
 
$person = new SayName();
```
######Namespaces
PHP Namespaces provide a way in which to group related classes, interfaces, functions and constants.

Namespaces:
- Provide a way to better organize and group together classes according to functionality
- They allow the same name to be used for more than one class

For example let say you have multiple folders in the root folder. Each of this folder has an index.php file that contains a certain login.  As a concrete example, the file index.php can exist in both directory `/home/bazeng` and in `/home/other`, but two copies of index.php cannot co-exist in the same directory. In addition, to access the index.php file outside of the `/home/bazeng` directory, we must prepend the directory name to the file name using the directory separator to get `/home/bazeng/index.php`. 

In the PHP world, namespaces are designed to solve two problems:

- Name collisions between code you create, and internal PHP classes/functions/constants or third-party classes/functions/constants.
- Ability to alias (or shorten) Extra_Long_Names designed to alleviate the first problem, improving readability of source code.

Namespaces are declared at the top most section of a class. Namespace names are case-insensitive. For practical purpose create a folder called namespaces, inside create a `folder` called `Car` and create an `index.php` and copy the code below: 

```
<?php
namespace Car;

class Sedan{
   public model;
   public function __construct($model){
     $this->model = $model
   }
   public function getModel(){
     echo $this-> model
   }
}
class Lorry{
   public model;
   public function __construct($model){
     $this->model = $model
   }
   public function getModel(){
     echo $this-> model
   }
}


```
Go Back to the root folder namespaces and create an `index.php` file and copy this code:
```
<?php
namespace Car;
require "Car/index.php";
$sedan = new Sedan("Premio");
$lorry = new Lorry("Fuso");

$sedan->getModel();
echo "\n";
$lorry->getModel();

```
Host in your local server and in your browser navigate to the namespaces folder i.e `localhost/namespaces`. You can also clone this [repository](https://gitlab.com/samk3/phpnamespaces).

It can be useful to give a namespace or class an alias to make it easier to write. This is done with the `use` keyword:

```
use Car as C;
$car = new C();
```
######Iterables