Object Oriented Concepts +

Class: This is a programmer-defined datatype, which includes local functions as well as local data. You can think of a class as a template for making many instances of the same kind (or class) of object.

Object: An individual instance of the data structure defined by a class. You define a class once and then make many objects that belong to it. Objects are also known as instance.

Member Variable/Properties: These are the variables defined inside a class. This data will be invisible to the outside of the class and can be accessed via member functions. These variables are called attribute of the object once an object is created.

Member function/Method: These are the function defined inside a class and are used to access object data.

Inheritance: When a class is defined by inheriting existing function of a parent class then it is called inheritance. Here child class will inherit all or few member functions and variables of a parent class.

Parent/Superclass/Base class: A class that is inherited from by another class. This is also called a base class or super class.

Child/Subclass/Derived Class: A class that inherits from another class. This is also called a subclass or derived class.

Mixed/Composite classes: A mixed class is another way to combine the functionality from other classes into a new class. A mixed class manages the properties of other classes and may only use a subset of the functionality of a class, whereas a derived class uses the complete set of functionality of its superclasses and usually extends this functionality.

Polymorphism: This is an object oriented concept where same function can be used for different purposes. For example function name will remain same but it make take different number of arguments and can do different task.

Overloading: Overloading means to replacing the same parental behavior in child class. A type of polymorphism in which some or all of operators have different implementations depending on the types of their arguments. Similarly functions can also be overloaded with different implementation.

Data Abstraction: Any representation of data in which the implementation details are hidden (abstracted).

Encapsulation: refers to a concept where we encapsulate all the data and member functions together to form an object.

Constructor: refers to a special type of function which will be called automatically whenever there is an object formation from a class.

Destructors: refers to a special type of function which will be called automatically whenever an object is deleted or goes out of scope.

Class & Object Creation+

Creating a class is very simple and easy declaring a class using class keyword followed by the name of that class.

    class myFirstClass {
            #code
        }

Member Function

class myFirstClass {
 
        function myFunction(){
            echo "function 1";
        }
 
    }

Member Variable/Properties

class myFirstClass {
	    $var1 = "hello";
        $var2;
    }

Creating Objects in PHP

Objects are basic building blocks of a PHP OOP program. An object is a combination of data and methods. In a OOP program, we create objects. These objects communicate together through methods. Each object can receive messages, send messages, and process data.

There are two steps in creating an object. First, we create a class. A class is a template for an object. It is a blueprint which describes the state and behavior that the objects of the class all share. A class can be used to create many objects. Objects created at runtime from a class are called instances of that particular class.

 
$objc1 = new myFirstClass();
$objc2 = new myFirstClass();

Calling member function of a class

$obj = new myFirstClass(); // object of the class
 
$obj->myFunction(); // member function call

Object attributes

Object attributes is the data bundled in an instance of a class. The object attributes are called instance variables or member fields. An instance variable is a variable defined in a class, for which each object in the class has a separate copy.

class Person {
    public $name = "";
}

$p1 = new Person();
$p1->name = "Jane";

$p2 = new Person();
$p2->name = "Beky";

echo $p1->name . "\n";  // output is Jane
echo $p2->name . "\n";  // output is Beky

Properties & Visibility+

Class member variables are called "properties". You may also see them referred to using other terms such as "attributes" or "fields"

Within class methods non-static properties may be accessed by using -> (Object Operator): $this->property (where property is the name of the property). Static properties are accessed by using the :: (Double Colon): self::$property

The pseudo-variable $this is available inside any class method when that method is called from within an object context. $this is a reference to the calling object (usually the object to which the method belongs, but possibly another object, if the method is called statically from the context of a secondary object).

Property Declaration

class SimpleClass
{
   // valid as of PHP 5.6.0:
   public $var1 = 'hello ' . 'world';
   // valid as of PHP 5.3.0:
   public $var2 = <<<EOD
hello world
EOD;
   // valid as of PHP 5.6.0:
   public $var3 = 1+2;
   // invalid property declarations:
   public $var4 = self::myStaticMethod();
   public $var5 = $myVar;

   // valid property declarations:
   public $var6 = myConstant;
   public $var7 = array(true, false);

   // valid as of PHP 5.3.0:
   public $var8 = <<<'EOD'
hello world
EOD;
}
class foo {
   // As of PHP 5.3.0
   public $bar = <<<'EOT'
bar
EOT;
   public $baz = <<<EOT
baz
EOT;
}
class MyClass
{
    public $public = 'Public';
    protected $protected = 'Protected';
    private $private = 'Private';

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private

/**
 * Define MyClass2
 */
class MyClass2 extends MyClass
{
    // We can redeclare the public and protected method, but not private
    protected $protected = 'Protected2';

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj2 = new MyClass2();
echo $obj2->public; // Works
echo $obj2->protected; // Fatal Error
echo $obj2->private; // Undefined
$obj2->printHello(); // Shows Public, Protected2, Undefined

Inheritance - Child/Parent Class Concept+

PHP class definitions can optionally inherit from a parent class definition by using the extends clause. The syntax is as follows:

  class Child extends Parent {
     //definition body
  }

The effect of inheritance is that the child class (or subclass or derived class) has the following characteristics:

Following example inherit Books class and adds more functionality based on the requirement.

class Books {
      /* Member variables */
      var $price;
      var $title;
      
      /* Member functions */
      function setPrice($par){
         $this->price = $par;
      }
      
      function getPrice(){
         echo $this->price;
      }
      
      function setTitle($par){
         $this->title = $par;
      }
      
      function getTitle(){
         echo $this->title ;
      }
   }


class Novel extends Books {
   var publisher;
   function setPublisher($par){
     $this->publisher = $par;
   }
   function getPublisher(){
     echo $this->publisher;
   }
}

The variable $this is a special variable and it refers to the same object.

Now apart from inherited functions, class Novel keeps two additional member functions.


class Base {
    function __construct() {
       echo "Construction of Base class <br>";
    }
}

class Derived extends Base {
    function __construct() {
        parent::__construct();
        echo "Construction of Derived class<br>";
    }
}

$obj1 = new Base();
$obj2 = new Derived(); 

//The output is below:
Construction of Base class
Construction of Base class
Construction of Derived class

In the constructor of the Derived class, we call the parent constructor. We use the parent keyword, followed by two colons and the __construct() method. The constructors of the parent classes must be called explicitly.

class Foo
{
    public function printItem($string)
    {
        echo 'Foo: ' . $string . PHP_EOL;
    }
    
    public function printPHP()
    {
        echo 'PHP is great.' . PHP_EOL;
    }
}

class Bar extends Foo
{
    public function printItem($string)
    {
        echo 'Bar: ' . $string . PHP_EOL;
    }
}

$foo = new Foo();
$bar = new Bar();
$foo->printItem('baz'); // Output: 'Foo: baz'
$foo->printPHP();       // Output: 'PHP is great' 
$bar->printItem('baz'); // Output: 'Bar: baz'
$bar->printPHP();       // Output: 'PHP is great'

Class Constants +

PHP enables to create class constants. These constants do not belong to a concrete object. They belong to the class. By convention, constants are written in uppercase letters.

It is possible to define constant values on a per-class basis remaining the same and unchangeable. Constants differ from normal variables in that you don't use the $ symbol to declare or use them. The default visibility of class constants is public.

The value must be a constant expression, not (for example) a variable, a property, or a function call.

It's also possible for interfaces to have constants. Look at the interface documentation for examples.

As of PHP 5.3.0, it's possible to reference the class using a variable. The variable's value can not be a keyword (e.g. selfparent and static).

Note that class constants are allocated once per class, and not for each class instance.

class Math {
    const PI = 3.14159265359;
    public function getPI() {
        echo self::PI;
    }
}
$math = new Math();
echo Math::PI, "\n";
echo $math->getPI(), "\n";
class MyClass
{
    const CONSTANT = 'constant value';

    function showConstant() {
        echo  self::CONSTANT . "\n";
    }
}

echo MyClass::CONSTANT . "\n";

$classname = "MyClass";
echo $classname::CONSTANT . "\n"; // As of PHP 5.3.0

$class = new MyClass();
$class->showConstant();

echo $class::CONSTANT."\n"; // As of PHP 5.3.0

Support for initializing constants with Heredoc and Nowdoc syntax was added in PHP 5.3.0.

class foo {
    // As of PHP 5.3.0
    const BAR = <<<'EOT'
bar
EOT;
    // As of PHP 5.3.0
    const BAZ = <<<EOT
baz
EOT;
}

It is possible to provide a scalar expression involving numeric and string literals and/or constants in context of a class constant. Constant expression support was added in PHP 5.6.0.

const ONE = 1;

class foo {
    // As of PHP 5.6.0
    const TWO = ONE * 2;
    const THREE = ONE + self::TWO;
    const SENTENCE = 'The value of THREE is '.self::THREE;
}
class Foo {
    // As of PHP 7.1.0
    public const BAR = 'bar';
    private const BAZ = 'baz';
}
echo Foo::BAR; // output is - bar
echo Foo::BAZ; // error- cannot access private constant

Encapsulation - Public/Private/Protected - (Access Control Modifiers or visibility) +

Encapsulation hides data being accessed from outside a class directly.

There is 3 types in encapsulation:

Public Members:

Unless you specify otherwise, properties and methods of a class are public. That is to say, they may be accessed in three possible situations:

If you wish to limit the accessibility of the members of a class then you define class members as private or protected.

 class myFirstClass {
       public function myFunction(){    // if we dont use public keyword its by default public then
            echo "public one";
        }
    }

Private Members:

By designating a member private, you limit its accessibility to the class in which it is declared. The private member cannot be referred to from classes that inherit the class in which it is declared and cannot be accessed from outside the class. A class member can be made private by using private keyword in front of the member.

A class member can be made private by using private keyword infront of the member.

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

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

When MyClass class is inherited by another class using extends, myPublicFunction() will be visible, as will $driver. The extending class will not have any awareness of or access to myPrivateFunction and $car, because they are declared private.

Protected Members:

A protected property or method is accessible in the class in which it is declared, as well as in classes that extend that class. Protected members are not available outside of those two kinds of classes. A class member can be made protected by using protected keyword infront of the member.

A class with protected property or method can be accessible within the class and it can be accessed in the class which extends that class. A class member can be made protected by using protected keyword infront of the member.

class myFirstClass {
        function myFunction(){
            echo "public one";
        }
        protected function myprotectedFunction(){
            echo "I'm  visible in child class!";
        }
    }
Property declaration
/** Define MyClass */

class MyClass
{
    public $public = 'Public';
    protected $protected = 'Protected';
    private $private = 'Private';

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private

/** Define MyClass2 */

class MyClass2 extends MyClass
{
    // We can redeclare the public and protected method, but not private
    protected $protected = 'Protected2';

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj2 = new MyClass2();
echo $obj2->public; // Works
echo $obj2->protected; // Fatal Error
echo $obj2->private; // Undefined
$obj2->printHello(); // Shows Public, Protected2, Undefined

Method Visibility

Class methods may be defined as public, private, or protected. Methods declared without any explicit visibility keyword are defined as public.

Method Declaration
/** Define MyClass */

class MyClass
{
    // Declare a public constructor
    public function __construct() { }

    // Declare a public method
    public function MyPublic() { }

    // Declare a protected method
    protected function MyProtected() { }

    // Declare a private method
    private function MyPrivate() { }

    // This is public
    function Foo()
    {
        $this->MyPublic();
        $this->MyProtected();
        $this->MyPrivate();
    }
}

$myclass = new MyClass;
$myclass->MyPublic(); // Works
$myclass->MyProtected(); // Fatal Error
$myclass->MyPrivate(); // Fatal Error
$myclass->Foo(); // Public, Protected and Private work


/** Define MyClass2  */

class MyClass2 extends MyClass
{
    // This is public
    function Foo2()
    {
        $this->MyPublic();
        $this->MyProtected();
        $this->MyPrivate(); // Fatal Error
    }
}

$myclass2 = new MyClass2;
$myclass2->MyPublic(); // Works
$myclass2->Foo2(); // Public and Protected work, not Private

class Bar 
{
    public function test() {
        $this->testPrivate();
        $this->testPublic();
    }

    public function testPublic() {
        echo "Bar::testPublic\n";
    }
    
    private function testPrivate() {
        echo "Bar::testPrivate\n";
    }
}

class Foo extends Bar 
{
    public function testPublic() {
        echo "Foo::testPublic\n";
    }
    
    private function testPrivate() {
        echo "Foo::testPrivate\n";
    }
}

$myFoo = new Foo();
$myFoo->test(); // Bar::testPrivate 
                // Foo::testPublic

Visibility from other objects

Objects of the same type will have access to each others private and protected members even though they are not the same instances. This is because the implementation specific details are already known when inside those objects.

Accessing private members of the same object type
class Test
{
    private $foo;

    public function __construct($foo)
    {
        $this->foo = $foo;
    }

    private function bar()
    {
        echo 'Accessed the private method.';
    }

    public function baz(Test $other)
    {
        // We can change the private property:
        $other->foo = 'hello';
        var_dump($other->foo);

        // We can also call the private method:
        $other->bar();
    }
}

$test = new Test('test');

$test->baz(new Test('other'));
?>
The above example will output:

string(5) "hello"
Accessed the private method.

Function Overloading VS Funciton Overriding+

Function Overloading is when multiple function with same name exist in a class. Function Overriding is when function have same prototype in base class as well as derived class.

Function Overloading can occur without inheritance. Function Overriding occurs when one class is inherited from another class.

Function/Method Overloading +

From outside of the class, according to class user demand, automatically creating any property or method (Which has not been define before) in class is called Overloading. We can also tell that, Overloading is a process of how to automatically create a property and method according to class user demand.

Types of Overloading

Overloading is basically two types:

  1. Property Overloading
  2. Method Overloading

What is Property Overloading?

From outside of the class, according to class user demand, automatically creating any property (Which has not been define before) in class is called Property Overloading. We can also call Property Overloading as a way to automatically create property according to class user demand.

At property overloading, we set the value to the overloaded property with the __set() function, Get the value of Overloaded property with the __get() function, With the __unset() function, we set the value of the overloaded property to empty from the outside of the class and check the value of the Overloaded property with the __isset() function from outside of the class.

__set() is run when writing data to inaccessible properties.

__get() is utilized for reading data from inaccessible properties.

__isset() is triggered by calling isset() or empty() on inaccessible properties.

__unset() is invoked when unset() is used on inaccessible properties.

The $name argument is the name of the property being interacted with. The __set() method's $value argument specifies the value the $name'ed property should be set to.

Property overloading only works in object context. These magic methods will not be triggered in static context. Therefore these methods should not be declared static. As of PHP 5.3.0, a warning is issued if one of the magic overloading methods is declared static.

What is the job of __set() and __get() functions for Overload property?

The __set() function is used to create a new property from the outside of the class. And value can be set on the property created. The value of the overloaded property with the __get() function can be obtained from the outside of the class.

class PropertyTest {
    /**  Location for overloaded data.  */

    private $data = array();

    public function __set($name, $value) {

    echo "Setting '$name' Property to '$value'\n";
		$this->data[$name] = $value;
    }

    public function __get($name) {

        echo "Getting '$name' Property with Value : ";

		if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }
    }
}

$obj = new PropertyTest;
$obj->a = "Masud Alam";
echo $obj->a . "\n";

Result:
Setting 'a' Property to Masud Alam
Getting 'a' Property with value : Masud Alam

Explanation: First we create a property $a with __set() function (which was not defined in our class),also we set a value for $a. At the same time, keep a property name and its value in a private array property named $data. Then, with the __get() function, we get the value of the $a property from $data array property.

What is the act of the __isset() function to overload the property?

When an overloaded property is checked with the isset() function from the outside of class, Then the __isset () function is automatically executes in class. And allows you to check whether there is a value of overloaded property.

class PropertyTest {
    /**  Location for overloaded data.  */
    private $data = array();

    public function __set($name, $value) {
        echo "Setting '$name' Property to '$value'\n";
        $this->data[$name] = $value;
    }

    public function __get($name) {

        echo "Getting '$name' Property with Value : ";

		if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }
    }

    // Checking Property Value is set?

    public function __isset($name) {

        echo "Is '$name' Property set?\n";

        echo isset($this->data[$name])?"Yes '$name' Property is set":"No '$name' Property is Not set";

        echo "\n";
    }
}

$obj = new PropertyTest;
$obj->a = "Masud Alam";
echo $obj->a . "\n";

isset($obj->a);
isset($obj->b);

Result:
Setting 'a' Property to Masud Alam
Getting 'a' Property with value : Masud Alam
Is 'a' Property set?
Yes 'a' property is set
Is 'b' property is set?
No 'b' property is not set

Explanation: Notice, at line number 35 and 36 with function isset(), we have checked that is there any value in the two unknown property in the class, And with the isset () function call, the __isset () function is automatically executed on line 21 in our class. Checks whether the overloaded property has value.

What is the act of the __unset() function to overload the property?

When an overloaded property is checked with the unset () function from the outside of class, Then the __unset() function is automatically executes in class. And allows the value of the overloaded property to be unset.

class PropertyTest
{
    /**  Location for overloaded data.  */
    private $data = array();
 
    public function __set($name, $value)
    {
        echo "Setting '$name' to '$value'\n";
        $this->data[$name] = $value;
    }
 
    public function __get($name)
    {
         echo "Getting '$name' Property with Value : ";
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }
    }
     
    public function __isset($name)
    {
        echo "Is '$name' Property set?\n";
        echo isset($this->data[$name])?"Yes '$name' Property is set":"No '$name' Property is Not set";
        echo "\n";
    }
 
    public function __unset($name)
    {
        echo "Unsetting '$name'\n";
        unset($this->data[$name]);
    }
 
}
 
 
$obj = new PropertyTest;
 
$obj->a = "Masud Alam";
echo $obj->a . "\n";
echo isset($obj->a);
unset($obj->a);
echo isset($obj->a);
echo "\n";

Result:
Setting 'a' Property to Masud Alam
Getting 'a' Property with value : Masud Alam
Is 'a' Property set?
Yes 'a' property is set
Unsetting 'a'
Is 'a' property is set?
No 'a' property is not set

Explanation: Notice, we have call unset() function at line number 42 to unset the value of a unknown property, With the unset () function call, the __unset() function is automatically executed on line number 28 in our class. Unset the value of the overloaded property.

What is Method Overloading?

From outside of the class, according to class user demand, automatically creating any method (Which has not been define before) in class is called Property Overloading. We can also call Method Overloading as a way to automatically create method according to class user demand.

In Method overloading, we create an Overloaded Method from the outside of class with the __call() function and set the Parameter to overloaded method. Make an overloaded static method from the outside of the class with the __callStatic() function and set the Parameter to overloaded static method

class MethodTest
{
    public function __call($name, $arguments)
    {
        echo "Calling object method '$name' "
             . implode(', ', $arguments). "\n";
    }
 
    public static function __callStatic($name, $arguments)
    {
        echo "Calling static method '$name' "
             . implode(', ', $arguments). "\n";
    }
}
 
$obj = new MethodTest;
$obj->runTest('in object context');
 
MethodTest::runTest('in static context');

Function/Method Overriding +

Function definitions in child classes override definitions with the same name in parent classes. In a child class, we can modify the definition of a function inherited from parent class.

In the follwoing example getPrice and getTitle functions are overriden to retrun some values.

    function getPrice(){
       echo $this->price . "<br/>";
       return $this->price;
    }
    function getTitle(){
       echo $this->title . "<br/>";
       return $this->title;
    }

Constructor/Destructor Functions+

Constructor Functions are special type of functions which are called automatically whenever an object is created of the class. So we take full advantage of this behaviour, by initializing many things through constructor functions.

PHP provides a special function called __construct() to define a constructor. You can pass as many as arguments you like into the constructor function.

Following example will create one constructor for Books class and it will initialize price and title for the book at the time of object creation.

class myFirstClass {
        __construct($par1, $par2){
            $this->price = $par1;
            $this->title = $par2;
        }
        function myFunction(){
            echo $this->price." ".$this->title;
        }
    }
    $obj = new myFirstClass(1200,'PHP My Essential');
    $obj->myFunction();
Note: Parent constructors are not called implicitly if the child class defines a constructor. In order to run a parent constructor, a call to parent::__construct() within the child constructor is required. If the child does not define a constructor then it may be inherited from the parent class just like a normal class method (if it was not declared as private).
class BaseClass {
   function __construct() {
       print "In BaseClass constructor\n";
   }
}

class SubClass extends BaseClass {
   function __construct() {
       parent::__construct();
       print "In SubClass constructor\n";
   }
}

class OtherSubClass extends BaseClass {
    // inherits BaseClass's constructor
}

// In BaseClass constructor
$obj = new BaseClass();

// In BaseClass constructor
// In SubClass constructor
$obj = new SubClass();

// In BaseClass constructor
$obj = new OtherSubClass();

For backwards compatibility with PHP 3 and 4, if PHP cannot find a __construct() function for a given class, and the class did not inherit one from a parent class, it will search for the old-style constructor function, by the name of the class. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics.

Warning

Old style constructors are DEPRECATED in PHP 7.0, and will be removed in a future version. You should always use __construct() in new code.

Unlike with other methods, PHP will not generate an E_STRICT level error message when __construct() is overridden with different parameters than the parent __construct() method has.

As of PHP 5.3.3, methods with the same name as the last element of a namespaced class name will no longer be treated as constructor. This change doesn't affect non-namespaced classes.

Constructors in namespaced classes

namespace Foo;
class Bar {
    public function Bar() {
        // treated as constructor in PHP 5.3.0-5.3.2
        // treated as regular method as of PHP 5.3.3
    }
}

Destructor:

Like a constructor function you can define a destructor function using function __destruct(). You can release all the resourceses with-in a destructor.

Static Keyword/Static Method and Properties/Late Static Binding +

Declaring class members or methods as static makes them accessible without needing an instantiation of the class. A member declared as static can not be accessed with an instantiated class object (though a static method can).

This page describes the use of the static keyword to define static methods and properties. static can also be used to define static variables and for late static bindings. Please refer to those pages for information on those meanings of static.

Declaring class properties or methods as static makes them accessible without needing an instantiation of the class. A property declared as static cannot be accessed with an instantiated class object (though a static method can).

Because static methods are callable without an instance of the object created, the pseudo-variable $this is not available inside the method declared as static.
In PHP 5, calling non-static methods statically generates an E_STRICT level warning.
In PHP 7, calling non-static methods statically is deprecated, and will generate an E_DEPRECATED warning. Support for calling non-static methods statically may be removed in the future.

Try out following example:

class Foo
{
    public static $my_static = 'foo';

    public function staticValue() {
        return self::$my_static;
    }
}
print Foo::$my_static . "\n";
$foo = new Foo();
print $foo->staticValue() . "\n";
class Foo {
    public static function aStaticMethod() {
        // ...
    }
}

Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod(); // As of PHP 5.3.0

Static Methods and Properties uses can be divided into two different way:

  1. Inside of the class
  2. Outside of the class

Static Method and Property uses outside of the class:

If we want to use static methods and properties outside of the class then we have to put (::) scope resolution operator after the class name, then we have to put static method of property name. For better understanding, see the following example:

class testStatic {

  	public static $count = 0;

	public static function counter(){

    echo "Its Static Counter";
  }

//Accessing Static Property and Method Outside of the Class
testStatic::$count=5; // Assigning Value to static Property
echo testStatic::$count; // Calling Static Property with Updated Value
echo "<br>";
testStatic::counter(); // Calling Static Method with Updated Value

Note: After the scope resolution operator, the property name must be start with a $ (dollar sign).

Static Method and Property uses inside of the class:

It we want to use static methods and properties inside of the class without $this pseudo-variable, then we have to put the class name or self keyword before (::) scope resolution operator, then we have to put the method or property name. For better understanding, see the following example:

class testStatic {

  public static $count = 0;

	public static function counter(){
	echo "Its Static Counter: ";
	echo self::$count++,"<br>"; // accessing static Property inside class
	}
}

// Calling Static Method Outside Class
testStatic::counter();
testStatic::counter();
testStatic::counter();

Result:

Its Static Counter: 0

Its Static Counter: 1

Its Static Counter: 2


What is Late Static Binding?

In PHP, to call static methods and properties within the class, instead of using $this pseudo-variable, we use (::) scope resolution operator after the class name or “self” keyword. “Self” keyword only specifies the class in which it’s been used. And for that the methods and properties of the parent class can not be inherits by the child class. And for that from PHP 5.3 instead of using “self” keyword we have start using “static” keyword to inherit any the methods and properties from parent class to child class. And this is called Late Static Binding. To understand better, see the following examples:

class Course{

    protected static $courseName = 'Professional PHP';

    public static function getCourseName(){

        return self::$courseName;

    }

}

class Student extends Course{

    protected static $courseName = 'Laravel';  

}
  
echo Student::getCourseName(); // Professional PHP, not Laravel

Explanation:

To solve the above problem, from PHP 5.3, Late static method has been added. Basically, Instead of “self” keyword, the “static” keyword is used, As it can points the class from which it’s been called. Let’s change our example above:

Example: Use of “static” keyword or Late Static Binding

class Course{

    protected static $courseName = 'Professional PHP';

    public static function getCourseName(){

        return static::$courseName;

    }

}

class Student extends Course{

    protected static $courseName = 'Laravel';  

}
   
echo Student::getCourseName(); // Laravel

Static Property Example:

class Foo
{
    public static $my_static = 'foo';

    public function staticValue() {
        return self::$my_static;
    }
}

class Bar extends Foo
{
    public function fooStatic() {
        return parent::$my_static;
    }
}


print Foo::$my_static . "\n";

$foo = new Foo();
print $foo->staticValue() . "\n";
print $foo->my_static . "\n";      // Undefined "Property" my_static 

print $foo::$my_static . "\n";
$classname = 'Foo';
print $classname::$my_static . "\n"; // As of PHP 5.3.0

print Bar::$my_static . "\n";
$bar = new Bar();
print $bar->fooStatic() . "\n";

Scope Resolution Operator (::) +

When and how to use the double-colon:

The Scope Resolution Operator (also called Paamayim Nekudotayim) or in simpler terms, the double colon, is a token that allows access to static, constant, and overridden properties or methods of a class.

When referencing these items from outside the class definition, use the name of the class.

As of PHP 5.3.0, it's possible to reference the class using a variable. The variable's value can not be a keyword (e.g. self, parent and static).

Example #1 :: from outside the class definition

<?php
class MyClass {
    const CONST_VALUE = 'A constant value';
}

$classname = 'MyClass';
echo $classname::CONST_VALUE; // As of PHP 5.3.0

echo MyClass::CONST_VALUE;
?>

Three special keywords self, parent and static are used to access properties or methods from inside the class definition.

Example #2 :: from inside the class definition

<?php
class OtherClass extends MyClass
{
    public static $my_static = 'static var';

    public static function doubleColon() {
        echo parent::CONST_VALUE . "\n";
        echo self::$my_static . "\n";
    }
}

$classname = 'OtherClass';
echo $classname::doubleColon(); // As of PHP 5.3.0

OtherClass::doubleColon();
?>

Sometimes it is useful to refer to functions and variables in base classes or to refer to functions in classes that have not yet any instances. The :: operator is being used for this.

<?php
class A {
    function example() {
        echo "I am the original function A::example().<br />\n";
    }
}

class B extends A {
    function example() {
        echo "I am the redefined function B::example().<br />\n";
        A::example();
    }
}

// there is no object of class A.
// this will print
//   I am the original function A::example().<br />
A::example();

// create an object of class B.
$b = new B;

// this will print 
//   I am the redefined function B::example().&br />
//   I am the original function A::example().<br />
$b->example();
?>

In general, :: is used for scope resolution, and it may have either a class name, parent, self, or (in PHP 5.3) static to its left. parent refers to the scope of the superclass of the class where it's used; self refers to the scope of the class where it's used; static refers to the "called scope" .

Autoloading Classes/Namespaces +

Many developers writing object-oriented applications create one PHP source file per class definition. One of the biggest annoyances is having to write a long list of needed includes at the beginning of each script (one for each class).

In PHP 5, this is no longer necessary. The spl_autoload_register() function registers any number of autoloaders, enabling for classes and interfaces to be automatically loaded if they are currently not defined. By registering autoloaders, PHP is given a last chance to load the class or interface before it fails with an error.

Tip

Whilst the __autoload() function can also be used for autoloading classes and interfaces, its preferred to use the spl_autoload_register() function. This is because it is a more flexible alternative (enabling for any number of autoloaders to be specified in the application, such as in third party libraries). For this reason, using __autoload() is discouraged and it may be deprecated in the future.

Note:

Prior to PHP 5.3, exceptions thrown in the __autoload() function could not be caught in the catch block and would result in a fatal error. From PHP 5.3 and upwards, this is possible provided that if a custom exception is thrown, then the custom exception class is available. The __autoload() function may be used recursively to autoload the custom exception class.

Note:

Autoloading is not available if using PHP in CLI interactive mode.

Note:

If the class name is used e.g. in call_user_func() then it can contain some dangerous characters such as ../. It is recommended to not use the user-input in such functions or at least verify the input in __autoload().


https://developer.hyvor.com/php/autoload-classes-namespaces#autoload-classes

Abstract Classes +

PHP 5 introduces abstract classes and methods.

Note: Function definitions inside an abstract class must also be preceded by the keyword abstract. It is not legal to have abstract function definitions inside a non-abstract class.

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.

It is important to know that once we have an abstract method in a class, the class must also be abstract.

It is not allowed to create an instance of a class that has been defined as abstract.". It only means you cannot initialize an object from an abstract class. Invoking static method of abstract class is still feasible. For example:

abstract class Foo
{
    static function bar()
    {
        echo "test\n";
    }
}

Foo::bar();

Abstract Class 
1. Contains an abstract method
2. Cannot be directly initialized
3. Cannot create an object of abstract class
4. Only used for inheritance purposes

Abstract Method
1. Cannot contain a body
2. Cannot be defined as private
3. Child classes must define the methods declared in abstract class 

abstract class AbstractClass
{
    // Force Extending class to define this method
    abstract protected function getValue();
    abstract protected function prefixValue($prefix);

    // Common method
    public function printOut() {
        print $this->getValue() . "\n";
    }
}

class ConcreteClass1 extends AbstractClass
{
    protected function getValue() {
        return "ConcreteClass1";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass1";
    }
}

class ConcreteClass2 extends AbstractClass
{
    public function getValue() {
        return "ConcreteClass2";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass2";
    }
}

$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";

$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') ."\n";

The above example will output:

ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2

Another Example:

abstract class AbstractClass
{
    // Our abstract method only needs to define the required arguments
    abstract protected function prefixName($name);

}

class ConcreteClass extends AbstractClass
{

    // Our child class may define optional arguments not in the parent's signature
    public function prefixName($name, $separator = ".") {
        if ($name == "Pacman") {
            $prefix = "Mr";
        } elseif ($name == "Pacwoman") {
            $prefix = "Mrs";
        } else {
            $prefix = "";
        }
        return "{$prefix}{$separator} {$name}";
    }
}

$class = new ConcreteClass;
echo $class->prefixName("Pacman"), "\n";
echo $class->prefixName("Pacwoman"), "\n";

The above example will output:

Mr. Pacman
Mrs. Pacwoman

Explained in Bangla

কিছু ক্লাসকে আমরা এ্যাবস্ট্রাক্ট হিসেবে ডিক্লেয়ার করতে পারি । এসব ক্লাস থেকে সরাসরি অবজেক্ট ইনস্ট্যান্স তৈরি করা সম্ভব হয় না । কিন্তু এদের কে ইনহেরিট করা সম্ভব । কোন ক্লাসের একটি মেথড এ্যাবস্ট্রাক্ট হলে সেটিকে এ্যাবস্ট্রাক্ট ক্লাস হিসেবে ডিক্লেয়ার করতে হবে ।

এ্যাবস্ট্রাক্ট মেথড গুলোর বেলায় শুধুই মেথড সিগনেচার ডিফাইন করে দিতে হয় । মূল ইম্প্লিমেন্টেশন দেওয়া হয় না । প্যারেন্ট ক্লাসে ডিফাইন করা সকল এ্যাবস্ট্রাক্ট মেথড অবশ্যই চাইল্ড ক্লাসে ইম্প্লিমেন্ট করতে হবে । এসময় ভিজিবিলিটি একই অথবা বেশী ওপেন (প্রাইভেট থাকলে প্রাইভেট কিংবা প্রটেক্টেড, প্রটেক্টেড থাকলে প্রটেক্টেড কিংবা পাবলিক) রাখা আবশ্যক । একই সাথে ফাংশনের সিগনেচারও ম্যাচ করতে হবে, আপনি চাইলেই চাইল্ড ক্লাসে কোন মেথডের একটি প্যারামিটার যোগ বা বাদ দিতে পারবেন না ।

এ্যাবস্ট্রাক্ট ক্লাস অনেকটা ইন্টারফেইসের মত শুধু এখানে শুধু মাত্র নির্দিষ্ট মেথড গুলো আমরা এ্যাবস্ট্রাক্ট রেখে বাকি মেথডগুলোর ইম্প্লিমেন্টেশন তৈরি করে দিতে পারি ।

abstract class AbstractClass
{
    // Force Extending class to define this method
    abstract protected function getValue();
    abstract protected function prefixValue($prefix);

    // Common method
    public function printOut() {
        print $this->getValue() . "\n";
    }
}

class ConcreteClass1 extends AbstractClass
{
    protected function getValue() {
        return "ConcreteClass1";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass1";
    }
}

class ConcreteClass2 extends AbstractClass
{
    public function getValue() {
        return "ConcreteClass2";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass2";
    }
}

$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";

$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') ."\n";

এখানে একই এ্যাবস্ট্রাক্ট ক্লাস থেকে আমরা দুটি ক্লাস তৈরি করেছি । এবং প্রত্যেকটি সাবক্লাসে আমরা এ্যাবস্ট্রাক্ট মেথডগুলো নিজেদের মত করে ইম্প্লিমেন্ট করেছি । কিন্তু printOut() মেথডটি মূল ক্লাসেই ডিফাইন করা ।

Concrete Class VS Abstract Class +

The only real difference is that a concrete class can be instantiated because it provides (or inherits) the implementation for all of its methods. An abstract class cannot be instantiated because at least one method has not been implemented. Abstract classes are meant to be extended.

Interfaces +

An Interface is kind of like a class, although you can’t use it directly, classes must implement them. Think of it as a prototype or a blueprint of a class. In your interface you will declare the functions, but they won’t actually have any code inside of them. You also aren’t allowed to define your data storage.

In the classes that you implement your interface in, you must use all of the defined functions of the interface, otherwise you’ll get a PHP error. This is because our program which will interact with the implemented classes expect our class to be able to communicate in the methods that we define here. This way, as we modify functionality elsewhere in the application, or add extra functionality in our implementing classes, we don’t break backwards compatibility.

As of PHP5, it is possible to define an interface, like this:

interface IMyInterface{
 // methods...
}
interface IMyInterface{
 const INTERFACE_CONSTANT_1 = 1;
 const INTERFACE_CONSTANT_2 = 'a string';
 
 public function method_1();
 public function method_2();
}

To implement an interface, you use the implements operator as follows:

class MyClass implements IMyInterface{
 public function method_1(){
 // method 1 implementation 
 }
 public function method_2(){
 // method 2 implementation
 }
}

When a class implements an interface, we also called it a concrete class. The concrete class must implement all methods the interface with the same names and signatures.

The next example shows how interfaces can extend from multiple other interfaces.

interface IInfo {
    public function do_inform();
}

interface IVersion {
    public function get_version();
}

interface ILog extends IInfo, IVersion {
    public function do_log();
}

class DBConnect implements ILog {

    public function do_inform() {
        echo "This is a DBConnect class\n";
    }

    public function get_version() {
        echo "Version 1.02\n";
    }

    public function do_log() {
        echo "Logging\n";
    }

    public function connect() {
        echo "Connecting to the database\n";
    }
}

$db = new DBConnect();
$db->do_inform();
$db->get_version();
$db->do_log();
$db->connect();

ইন্টারফেইসের মাধ্যমে আমরা বলে দেই একটা ক্লাসের কোন কোন মেথড অবশ্যই থাকা লাগবে । কিন্তু আমরা এর মূল ইম্প্লিমেন্টেশনটা নির্দিষ্ট করে দেই না ।

আমরা একটা ইন্টারফেইস ডিফাইন করি interface কিওয়ার্ডটি দিয়ে । এবং যে সব ক্লাস এই ইন্টারফেইস মেনে চলে তারা এই ইন্টারফেইসকে implement করে ।

ইন্টারফেইস ডিফাইন করা হয় সাধারনভাবে ক্লাসের মত করেই । ইন্টারফেইসের মেথডগুলোর শুধু সিগনেচার (কি কি প্যারামিটার নেয়) ডিফাইন করে দেওয়া হয় কিন্তু এই মেথডগুলোর বডি ডিফাইন করা হয় না ।

পিএইচপি ম্যানুয়াল থেকে একটি উদাহরন দেখে নেই:

// Declare the interface 'iTemplate'
interface iTemplate
{
    public function setVariable($name, $var);
    public function getHtml($template);
}

// Implement the interface
// This will work
class Template implements iTemplate
{
    private $vars = array();

    public function setVariable($name, $var)
    {
        $this->vars[$name] = $var;
    }

    public function getHtml($template)
    {
        foreach($this->vars as $name => $value) {
            $template = str_replace('{' . $name . '}', $value, $template);
        }

        return $template;
    }
}

এখানে আমরা iTemplate নামে একটি ইন্টারফেইস ডিফাইন করেছি । আমাদের Template ক্লাসটি এই ইন্টারফেইস ইম্প্লিমেন্ট করে । খেয়াল করুন আমরা দেখছি কিভাবে ইন্টারফেইসে শুধু মেথড সিগনেচার এবং আমাদের মূল ক্লাসে তার ইম্প্লিমেন্টেশন তৈরি করা হয়েছে ।

আমরা যদি ইম্প্লিমেন্টেশন ক্লাসে ইন্টারফেইসের কোন মেথড ডিফাইন করতে ভুলে যাই সেক্ষেত্রে আমরা ফ্যাটাল এরর পাবো ।

পিএইচপিতে একটি ক্লাস অনেকগুলো ইন্টারফেইস ইম্প্লিমেন্ট করতে পারে তবে যদি দুইটি ইন্টারফেইসের একই নামের মেথড থাকে তাহলে সঙ্গত কারনেই কোন ক্লাস এই দুটি ইন্টারফেইস একই সাথে ইম্প্লিমেন্ট করতে পারবে না । সেটা করলে ঐ মেথডের নাম নিয়ে কনফ্লিক্ট তৈরি হবে ।

ইন্টারফেইস হলো অনেকটা ডেভেলপারের সাথে চুক্তি করার মতো । আমাদের চুক্তি মেনে নিতে হলে তাকে অবশ্যই আমাদের বলে দেওয়া মেথড ইম্প্লিমেন্ট করতে হবে । যখন কোন ক্লাস আমাদের ডিফাইন করা ইন্টারফেইস ইম্প্লিমেন্ট করে তখন আমরা ধরে নিতে পারি আমাদের বলে দেওয়া মেথডগুলো ঐ ক্লাসে আছে । এর ফলে আমরা ক্লাসের প্রয়োজনীয় ডিজাইন সম্পর্কে নিশ্চিত হতে পারি ।

Final Keyword +

PHP 5 introduces the final keyword, which prevents child classes from overriding a method by prefixing the definition with final. If the class itself is being defined final then it cannot be extended.

Following example results in Fatal error: Cannot override final method BaseClass::moreTesting()

class BaseClass {
   public function test() {
       echo "BaseClass::test() called<br>";
   }
  
   final public function moreTesting() {
       echo "BaseClass::moreTesting() called<br>";
   }
}

class ChildClass extends BaseClass {
   public function moreTesting() {
       echo "ChildClass::moreTesting() called<br>";
   }
}

final class BaseClass {
   public function test() {
       echo "BaseClass::test() called\n";
   }

   // Here it doesn't matter if you specify the function as final or not
   final public function moreTesting() {
       echo "BaseClass::moreTesting() called\n";
   }
}

class ChildClass extends BaseClass {
}
// Results in Fatal error: Class ChildClass may not inherit from final class (BaseClass)

Note:Properties cannot be declared final, only classes and methods may be declared as final.

instanceof keyword +

The instanceof keyword is used to determine whether a PHP variable is an instantiated object of a certain class.

class A {

}
$obj = new A();

if ($obj instanceof A) {
   echo 'A'; // result A
}
class Cat {}
class Dog {}
class Bird {}

$objects = [ new Cat(), new Dog(), new Cat(), new Bird(), new Bird(), 
             new Dog(), new Dog(), new Cat(), new Bird() ];

shuffle($objects);

foreach ($objects as $object) {

    if ($object instanceof Cat) {
        echo "It is a Cat\n";
    } elseif ($object instanceof Dog) {
        echo "It is a Dog\n";
    } else if ($object instanceof Bird) {
        echo "It is a Bird\n";
    }
}

PHP OOP Method Chaining+

When many methods are called in a single instruction, in PHP’s term it is called Method Chaining. Let’s explain it a little easier, suppose you have a class named Person, where you have two private property named $name and $age. And there are two methods named setName() and setAge() to set value in $name and $age property. And lastly, to show the value of $name and $age property, there is a getResult() method. And suppose the name of our object is $person. Now if we do not want to call these three methods differently, instead we want to call the object by just calling it in a single instruction, then we can write like this $person->setName(“Masud Alam”)->setAge(33)->getResult(). This method is called Method Chaining in PHP’s terminology. Each method in class in Method Chaining, that is, the method of the class returns the object of that class. For Method Chaining, instead of writing value return in class, we have to write return $this;.

Example 1: General class and its results

	class person  {
	
		private $name="";
		private $age="";

		public function setName($name="") {
		  $this->name=$name;
		}

		public function setAge($age="20") {
		  $this->age=$age;
		}

		public function getInfo() {
		  echo "Hello, My name is ".$this->name." and my age is ".$this->age." years.";
		}
	}
  
	$person = new person();
	$person->setName("Masud Alam");
  	$person->setAge("33");
  	$person->getInfo();
	

Result:

Hello, My name is Masud Alam and my age is 33 years.

Note that we have call setName() and setAge() method separately to set value in $name and $age property of the class named person. And lastly, called the getResult() method to show value of $name and $age property.

Uses of Method Chaining:

If you want to convert the class used in example 1 to Method Chaining you have add return $this line after setName() and setAge() method. See the example below:

	class person  {
	
		private $name="";
		private $age="";

		public function setName($name="") {
		  $this->name=$name;
		}

		public function setAge($age="20") {
		  $this->age=$age;
		}

		public function getInfo() {
		  echo "Hello, My name is ".$this->name." and my age is ".$this->age." years.";
		}
	}
  
	 $person = new person();
	 $person->setName("Masud Alam")->setAge("33")->getInfo(); // Method chaining
	

Result:

Hello, My name is Masud Alam and my age is 33 years.

Explanation: Notice that we return $this pseudo-variable between setName() method and setAge() method. And we know that “$ this” pseudo-variable originally contained the object of the current class. Let’s first come to $person->setName(‘Masud Alam’), Its job is to call setName() Method and set Masud Alam to name property as value. Then setName () method will return $this, That means it will return the Object person.

Next let’s go to ->stAge(’33’), As we got the chain object from the previous setName() method, So, with that person object, we can call setAge(33) and set age 33 as value in age property. Again here we get $this as return, Similarly, here we will get chain as return to our object person.

Lastly by ->getInfo() method we get chain result for the previous series.


Static Method Chaining


Static Method Chaining is similar to General Method Chaining. But here for each static method, instead of writing return $this;, we have to write return new static;. See the example below:

	class oop {

		public static $val;

		public static function init($var) {
			static::$val=$var;
			return new static;     
	   }

		public static function add($var) {
			static::$val+=$var;
			return new static;
	   }
	   
		public static function sub($var) {
			static::$val-=$var;
			return new static;
		}
		public static function out() {
			return static::$val;
		}

	}

	echo oop::init(10)->add(2)->sub(5)->out(); //Result: 10+2-5=7
	echo "<br>";
	echo oop::sub(2)->out(); //Result: 7-2=5;
	

Understanding the ‘self’ keyword in PHP +

In PHP, you use the self keyword to access static properties and methods.

The problem is that you can replace $this->method() with self::method() anywhere, regardless if method() is declared static or not. So which one should you use?

$this নির্দেশ করে অবজেক্ট ইনস্ট্যান্স কে, self নির্দেশ করে ঐ ক্লাস কে ।

class ParentClass {
	function test() {
		self::who();	// will output 'parent'
		$this->who();	// will output 'child'
	}

	function who() {
		echo 'parent';
	}
}

class ChildClass extends ParentClass {
	function who() {
		echo 'child';
	}
}

$obj = new ChildClass();
$obj->test();

In this example, self::who() will always output ‘parent’, while $this->who() will depend on what class the object has.

Now we can see that self refers to the class in which it is called, while $this refers to the class of the current object.

So, you should use self only when $this is not available, or when you don’t want to allow descendant classes to overwrite the current method.

Polymorphism+

Polymorphism means different behavior for same operation like animal talk behavior is same talk but sound is different from all animals.

class animalClass {
      protected $name;
      public function __construct($animalName)
      {
         $this->name = $animalName;
      }
 
      public function getName()
      {
         return $this->name;
      }
 
      public function talk()
      {
         return $this->getName().' is talking';
      }
   }
 
   class dogClass extends animalClass
   {
      public function getName()
      {
         return 'Dog: '.parent::getName();
      }
   }
 
$a = new dogClass("My dog");
echo $a->talk();
$b = new animalClass("some Cat");
echo $b->talk();

Different animals different voice but same method talk.

Anonymous Classes+

Anonymous classes are the classes which are defined without any name. In PHP 7, we can define an anonymous class using keyword ‘new class’. This class can replace a full class definition.

$object = new class('argument'){

	public $property;
	
	public function _construct($argument){
		$this->property = $argument;
	}

}

We should all be familiar with what a named class looks like

class className {

 // defined properties and methods

};

$object = new className( 'arguments' );

An anonymous class is closely related to a named class, with the primary difference being that we instantiate it without a name.

$object = new class( 'arguments' ) {

 // defined properties and methods
};

As you can see here, we have created a new object at the same time we defined the class. The arguments in each case are passed to the defined constructor method.

The One-Off Object

Currently the PHP manual states that anonymous classes are useful when simple, one-off objects need to be created. What exactly do they mean?

You certainly could create a complex anonymous class, however if you wanted to take advantage of inheritance you would need a named class to extend.

The flip side of that coin is when you have a named class and want to create a simple object to use during the current execution.

For example you may need to override a property or method, you could create a new class that extends the named class, however that is the old way. The new way would be to create an anonymous class when you need that simple, one-off object.

class namedClass {
    
 protected $classType;
 protected $myProp = 'I am a named object';
    
 public function __construct($value) {
        
  $this->classType = $value;
        
 }
    
 public function returnProperty( $propName ) {
        
  if( !empty( $this->$propName ) ) {
            
   return $this->$propName;
            
  } else {
            
   return 'property not found';
            
  }
 }
    
}

This is a simple example of a named class which has two properties. When the class is instantiated, classType is assigned from a passed value and myProp is assigned in the class. It also has a method to return the value of any requested property by name.

$object = new namedClass( 'Named' );
echo $object -> returnProperty( 'classType' ); // Named
echo $object -> returnProperty( 'myProp' ); // I am a named object

Here we have instantiated a namedClass, assigning the value 'Named' to the classType property. Using the returnProperty method we can get the values assigned to the properties of the object.

In the next example, we will take it a step further and override the myProp property by extending the class using the old way.

class namedExtension extends namedClass {
    
    protected $myProp = 'I am an extended object';
    
}

$object = new namedExtension( 'Extended' );

echo $object -> returnProperty( 'classType' ); //Extended

echo $object -> returnProperty( 'myProp' ); //I am an extended object

As we can see here, we have instantiated a namedExtension of the namedClass, assigning the value 'Extended' to the classType property and overriding the myProp value.

So far there is nothing new here, this is how we have been working with classes in PHP. Now let us take a look at interacting with the namedClass anonymously, the new way.

$object = new class( 'Anonymous' ) extends namedClass {
    
    protected $myProp = 'I am an anonymous object';
};

echo $object -> returnProperty( 'classType' ); // Anonymous

echo $object -> returnProperty( 'myProp' ); // I am an anonymous object

Here we have created the object with an anonymous class. It is worth noting that the value 'Anonymous' used here is the argument passed to the constructor and not the class name. The syntax, new class, instantiates the anonymous class where instantiating a named class uses, new className.

One advantage is that we no longer need the named extension. Normally the named extension would be hidden away in some included file, if you ever needed to see how it is defined you have to start searching for it. With anonymous classes the definition is in the same place the object is created.

Object Iteration+

PHP 5 provides a way for objects to be defined so it is possible to iterate through a list of items, with, for example a  foreach statement. By default, all  visible properties will be used for the iteration.

class MyClass
{
    public $var1 = 'value 1';
    public $var2 = 'value 2';
    public $var3 = 'value 3';

    protected $protected = 'protected var';
    private   $private   = 'private var';

    function iterateVisible() {
       echo "MyClass::iterateVisible:\n";
       foreach ($this as $key => $value) {
           print "$key => $value\n";
       }
    }
}

$class = new MyClass();

foreach($class as $key => $value) {
    print "$key => $value\n";
}
echo "\n";


$class->iterateVisible();

The above example will output:

var1 => value 1
var2 => value 2
var3 => value 3

MyClass::iterateVisible:
var1 => value 1
var2 => value 2
var3 => value 3
protected => protected var
private => private var

Oject Cloning+

When you have created a copy of an object using “=” operator. The reference of both the object (original and the one which is created) has the same reference. After copying, when you will change the value of the variable of one object than other object will automatically gets changed. Following is an example which shows how variable of one object gets changed:

class employee {

    private $name;
    public function setName($emp_name) {
             $this->name = $emp_name;

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

    }
}

$obj1 = new employee();
$obj1->setName("Neha");

$obj2 = $obj1; //only reference or memory assigned to $obj2
$obj2->setName("Ragini");

echo $obj1->getName()."</br>"; // Neha will be replaced by Ragini
echo $obj2->getName()."</br>";

$obj3 = new employee();
$obj3->setName("Mizan");
echo $obj3->getName()."</br>"; // As we declared new object so this time it wont replace previous one

As in the above example, we can say that when the object is copied directly it is copied by reference, not by value. It means when you have changed the main object value then copied object is also gets affected and also when you will change the value of copied object then the main object value will also gets changed.

In PHP 5, however, objects are always passed by reference. ALL OF THEM. This is the key. So that means this same code in PHP 5 won’t make a copy, but actually just duplicate it. In order to make an actual copy that you can modify separately, you need to clone it:

class employee {

    private $name;
    public function setName($emp_name) {
             $this->name = $emp_name;

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

    }
}

$obj1 = new employee();
$obj1->setName("Neha");

$obj2 = clone $obj1; // Instead of assigning this time we are cloning
$obj2->setName("Ragini");

echo $obj1->getName()."
"; // Neha echo $obj2->getName()."
"; // Ragini
Object Cloning using magic method

Object cloning can also be done using __clone magical method. Before we go further on __clone method we will give you a brief knowledge about magical method.

The magic methods are one with special names which are executed in response to some events. These magic methods are predefined function by PHP compiler, starting with two underscore “__”, which indicate methods, which will be triggered by some PHP events. These functions are always defined inside the class and are not defined outside the class (they are not standalone functions). For further details please go to our previous article magical method.

class employee {
          private $name;
          public function text($emp_name) {
                   $this->name = $emp_name;

          }

          public function Name() {
                   return $this->name;
          }
          public function __clone() {
                   $obj1 = new employee();
                   $obj1->text($this->name);
                   return $obj1;
          }
}
$obj1 = new employee();
$obj1->text("Neha");
$obj2 = clone $obj1; //only reference or memory assigned to $c2
$obj2->text("Ragini");echo $obj1->Name()."</br>";
echo $obj2->Name();

output:
Neha // $obj1 displays Neha
Ragini // $obj2 also display Ragini

Type Hinting or Type Declaration+

Type declarations allow functions to require that parameters are of a certain type at call time. If the given value is of the incorrect type, then an error is generated: in PHP 5, this will be a recoverable fatal error, while PHP 7 will throw a TypeError exception.

To specify a type declaration, the type name should be added before the parameter name. The declaration can be made to accept NULLvalues if the default value of the parameter is set to NULL.

Type Description Minimum PHP version
Class/interface name The parameter must be an instanceof the given class or interface name. PHP 5.0.0
self The parameter must be an instanceof the same class as the one the method is defined on. This can only be used on class and instance methods. PHP 5.0.0
array The parameter must be an array. PHP 5.1.0
callable The parameter must be a valid callable. PHP 5.4.0
bool The parameter must be a boolean value. PHP 7.0.0
float The parameter must be a floating point number. PHP 7.0.0
int The parameter must be an integer. PHP 7.0.0
string The parameter must be a string. PHP 7.0.0
iterable The parameter must be either an array or an instanceof Traversable. PHP 7.1.0
object The parameter must be an object. PHP 7.2.0

Magic Methods+

In PHP, we can define some special functions that will be called automatically. Such functions require no function call to execute the code inside these functions. With this special feature, they can be referred as magic functions or magic methods.

The function names __construct()__destruct()__call()__callStatic()__get()__set()__isset()__unset()__sleep()__wakeup()__toString(), __invoke()__set_state()__clone() and  __debugInfo()  are magical in PHP classes. You cannot have functions with these names in any of your classes unless you want the magic functionality associated with them.


__call() is triggered when invoking inaccessible methods in an object context.

public mixed __call ( string $name , array $arguments )

__callStatic() is triggered when invoking inaccessible methods in a static context.

public static mixed __callStatic ( string $name , array $arguments )
The $name argument is the name of the method being called. The $arguments argument is an enumerated array containing the parameters passed to the $name'ed method.
class BaseClass {

    public function baseClassMethod(){
        echo 'Base Class Method<br>';
    }
}
class ChildClass extends BaseClass {


  public function childClassMethod() {
    echo 'Child Class Method<br>';
  }

  public function __call($method, $args) {
      echo "unknown method " . $method;
      return false;
  }
}

$testMagicMethod = new ChildClass();
$testMagicMethod->baseClassMethod(); // Base Class Method
$testMagicMethod->childClassMethod(); // Child Class Method
$testMagicMethod->other(); // unknown method other
class MethodTest
{
    public function __call($name, $arguments)
    {
        // Note: value of $name is case sensitive.
        echo "Calling object method '$name' "
             . implode(', ', $arguments). "\n";
    }

    /**  As of PHP 5.3.0  */
    public static function __callStatic($name, $arguments)
    {
        // Note: value of $name is case sensitive.
        echo "Calling static method '$name' "
             . implode(', ', $arguments). "\n";
    }
}

$obj = new MethodTest;
$obj->runTest('in object context');

MethodTest::runTest('in static context');  // As of PHP 5.3.0

Magic Methods Explained in php.net


Magic Methods Explained in howtocode.com.bd


Magic Methods Explained in zentut.com

Objects and References +

One of the key-points of PHP 5 OOP that is often mentioned is that "objects are passed by references by default". This is not completely true. This section rectifies that general thought using some examples.

A PHP reference is an alias, which allows two different variables to write to the same value. As of PHP 5, an object variable doesn't contain the object itself as value anymore. It only contains an object identifier which allows object accessors to find the actual object. When an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.

class A {
    public $foo = 1;
}  

$a = new A;
$b = $a;     // $a and $b are copies of the same identifier
             // ($a) = ($b) = <id>
$b->foo = 2;
echo $a->foo."\n";


$c = new A;
$d = &$c;    // $c and $d are references
             // ($c,$d) = <id>

$d->foo = 2;
echo $c->foo."\n";


$e = new A;

function foo($obj) {
    // ($obj) = ($e) = <id>
    $obj->foo = 2;
}

foo($e);
echo $e->foo."\n";

?>
The above example will output:

2
2
2

Object Serialization +

Serializing objects - objects in sessions  

serialize() returns a string containing a byte-stream representation of any value that can be stored in PHP. unserialize() can use this string to recreate the original variable values. Using serialize to save an object will save all variables in an object. The methods in an object will not be saved, only the name of the class.

In order to be able to unserialize() an object, the class of that object needs to be defined. That is, if you have an object of class A and serialize this, you'll get a string that refers to class A and contains all values of variables contained in it. If you want to be able to unserialize this in another file, an object of class A, the definition of class A must be present in that file first. This can be done for example by storing the class definition of class A in an include file and including this file or making use of the spl_autoload_register() function.

// classa.inc:
  
  class A {
      public $one = 1;
    
      public function show_one() {
          echo $this->one;
      }
  }
  
// page1.php:

  include("classa.inc");
  
  $a = new A;
  $s = serialize($a);
  // store $s somewhere where page2.php can find it.
  file_put_contents('store', $s);

// page2.php:
  
  // this is needed for the unserialize to work properly.
  include("classa.inc");

  $s = file_get_contents('store');
  $a = unserialize($s);

  // now use the function show_one() of the $a object.  
  $a->show_one();

If an application is using sessions and uses session_register() to register objects, these objects are serialized automatically at the end of each PHP page, and are unserialized automatically on each of the following pages. This means that these objects can show up on any of the application's pages once they become part of the session. However, the session_register() is removed since PHP 5.4.0.

It is strongly recommended that if an application serializes objects, for use later in the application, that the application includes the class definition for that object throughout the application. Not doing so might result in an object being unserialized without a class definition, which will result in PHP giving the object a class of __PHP_Incomplete_Class_Name, which has no methods and would render the object useless.

So if in the example above $a became part of a session by running session_register("a"), you should include the file classa.inc on all of your pages, not only page1.php and page2.php.

Beyond the above advice, note that you can also hook into the serialization and unserialization events on an object using the  __sleep() and __wakeup() methods. Using  __sleep() also allows you to only serialize a subset of the object's properties.


Serialization in PHP -blog.eduonix.com

Mixed/Composit Classes+

Traits +

A Trait is simply a group of methods that you want include within another class. A Trait, like an abstract class, cannot be instantiated on it’s own.

আমরা দেখেছি ক্লাস ইনহেরিট্যান্সের মাধ্যমে আমরা প্যারেন্ট ক্লাস থেকে চাইল্ড ক্লাসে মেথড ইনহেরিট করতে পারি । অর্থাৎ প্যারেন্ট ক্লাসে কোন মেথড তৈরি করা থাকলে আমরা সেটা চাইল্ড ক্লাসে ব্যবহার করতে পারি । কিন্তু অনেক সময় দেখা যায় একই ক্লাস হায়ারার্কিতে নেই এমন দুটি ক্লাসের কিছু কমন মেথড থাকতে পারে । অর্থাৎ এমন দুটি ক্লাস যারা একটি আরেকটিকে এক্সটেন্ড করে না কিন্তু দুটি ক্লাসেরই কমন মেথড থাকছে getName() নামে যেটা একই কাজ করে । এসব ক্ষেত্রে কোড রিইউজে সহায়তা করতে পিএইচপি 5.4.0 ভার্সন থেকে ট্রেইটস এর প্রচলন ।

ট্রেইটস ডিফাইন করা হয় ক্লাসের মত করেই তবে trait কিওয়ার্ডটি ব্যবহার করে । একটি ট্রেইটের ভিতরে একই ধরনের কিছু ফাংশনালিটি সম্পন্ন মেথড ডিফাইন করা থাকে । এরপরে কোন ক্লাসের ভিতরে আমরা ঐ ট্রেইটটি ইনক্লুড করলে ঐ মেথডগুলো আমরা এ্যাক্সেস করতে পারি ঠিক যেন ঐ ক্লাসেই মেথডগুলো ডিফাইন করা হয়েছিলো ।

An example of a Trait could be:

trait Sharable {

	public function share($item)  
	{  
	return ‘share this item’;  
	}

}  

You could then include this Trait within other classes like this:

class Post {

	use Sharable;

}

class Comment {

	use Sharable;

}  

Now if you were to create new objects out of these classes you would find that they both have the share() method available:

$post = new Post;  
echo $post->share(”); // ‘share this item’

$comment = new Comment;  
echo $comment->share(”); // ‘share this item’  
trait CommonMethods {
    public function getName() {
        return $this->name;
    }
}

class TestClass {
    use CommonMethods;
    private $name = "test class";
}

class AnotherClass {
    use CommonMethods;
    private $name = "another class";
}

$tc = new TestClass();
var_dump($tc->getName());

$ac = new AnotherClass();
var_dump($ac->getName());

এখানে TestClass এবং AnotherClass সম্পূর্ন ইনডিপেন্ডেন্ট দুটি ক্লাস । তারা CommonMethods ট্রেইটটি ব্যবহার করে । ফলে এই ট্রেইটের মেথডটি তারা সরাসরি ব্যবহার করতে পারে ।

পিএইচপিতে যেহেতু মাল্টিপল ইনহেরিট্যান্স নেই, অর্থাৎ কোন ক্লাস শুধুমাত্র একটা ক্লাসকেই এক্সটেন্ড করতে পারে তাই এক্ষেত্রে কমন মেথডগুলো গ্রুপিং এর জন্য ট্রেইট বেশ কার্যকর ভূমিকা পালন করতে পারে

Other +