Saturday 13 April 2019

Alter Path/Route in Drupal 8

In Drupal 7, path can be altered with the help of hook "hook_menu_alter()" but in Drupal 8 hook_menu is no longer exists so to alter the path in Drupal 8, we have to write a route subscriber.

To change the route behaviour, we need to use a service called RouteSubscriber.

  1. We need to tell Drupal that we have this service,
  2. Need to create the right class
Alter the path user/login, user/password handled by user module and remove /search handled by the Search module.
Create a custom module with custom service an RouteSubscriber.

Custom module: route_alter
create a route_alter.services.yml with custom service.

route_alter.info.yml
name: Alter Route
description: 'Alter custom or contributed Route'
type: module
core: 8.x

package: custom

route_alter.services.yml
services:
  route_alter.route_subscriber:
    class: Drupal\route_alter\Routing\AlterCustomRouteSubscriber
    tags:
      - { name: event_subscriber }

To implement RouteSubscriber, create file AlterCustomRouteSubscriber.php in directory src > Routing create class AlterCustomRouteSubscriber within this file.
Copy and paste below code in the above mentioned file.

<?php

/**
 * @file
 * Contains \Drupal\route_alter\Routing\AlterCustomRouteSubscriber.

 */

namespace Drupal\route_alter\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

/**
 * Listens to the dynamic route events.
 */
class AlterCustomRouteSubscriber extends RouteSubscriberBase {

  /**
   * {@inheritdoc}
   */
  public function alterRoutes(RouteCollection $collection) {
    // Change path '/user/login' to '/login'.
    if ($route = $collection->get('user.login')) {
      $route->setPath('/login');
    }
    // Always deny access to '/user/logout'.
    // Note that the second parameter of setRequirement() is a string.
    if ($route = $collection->get('user.logout')) {
      $route->setRequirement('_access', 'FALSE');
    }
    // Remove the /search route.
    $collection->remove('search.view');
  }
}

Explanation for above code
\Drupal\route_alter\Routing\RouteSubscriber::alterRoutes method is an event subscriber because it extends RouteSubscriberBase. That's why class AlterCustomRouteSubscriber must be registered as an event subscriber service as in file route_alter.services.yml
  • With the help of alterRoutes method, dynamic routes can also added. 
  • If dynamic routes are standalone, use simpler route_callbacks solution and do not implement this class and event subscriber. 
  • If dynamic routes are dependent on other dynamic routes, then need to implement a class extending from RouteSubscriberBase

Thursday 11 April 2019

Function Overriding and Function Overloading in PHP

Function Overriding

What is method overriding in PHP?
Two methods with same name and parameter is called overriding. In Function overriding, both parent class and child class having method with same name and arguments. Purpose of method overriding is to change the behaviour of parent class method.

How to implement overriding in PHP?

Example of overriding in PHP:

<?php
  class parent_class {
    public function text() { //text() is a parent class method
      echo "Hello!! everyone I am parent class text method"."</br>";
    }
    public function test() {
      echo "Hello!! I am second method of parent class"."</br>";
    }
  }

  class child extends parent_class {
    public function text() {  // Text() parent class method which is override by child class
      echo "Hello!! Everyone i am child class";
    }
  }

  $obj = new parent_class();
  echo $obj->text(); // display the parent class method

  $obj= new parent_class();
  echo $obj->test();

  $obj= new child();
  echo $obj->text(); // display the child class method

?>
Output: 

Hello!! Everyone I am parent class text method

Hello!! I am second method of parent class

Hello!! everyone i am child class


As from the above example we can see how text() method of parent class is overridden by child class.

Function Overloading

Function overloading allows to create method with same name but different input parameter.
Method overloading means to assign extra work to same method.

How to implement overloading in PHP?

<?php
  class text {
    public function display($parameter1) {
      echo "Hello world!!";
    }
    public function display($parameter1,$parameter2) {
      echo "Hello India!!”;
    }
  }

  $obj = new text;
  echo $obj->display('Hello'); // It will show fatal error

?>

Output: 

Fatal error: Cannot redeclare text::display() 

Above code will give fatal error. With the above code output, overloading with the same name function cannot be possible. With the help of magic function(__call()) overloading is done. __call() function takes function and arguments.

Example, find the area of certain shapes where radius are given then it should return area of circle if height and width are given then it should give area of rectangle and others.

<?php
  class Shape {
    const Pi = 3.142 ;  // constant value
    
    // __call is magic function which accepts  
    // function name and arguments
    function __call($func_name, $argument) {
      // It will match the function name
      if ($func_name == 'area') {
        switch (count($argument)) {
          // If there is no argument 
  // return 0
  // If there is only one argument 
          // area of circle 
  // If there is two arguments 
          // area of rectangle 
          case 0 : return 0 ;
          case 1 : return self::Pi * $argument[0] ; // 3.14 * 5
          case 2 : return $argument[0] * $argument[1]; // 5 * 10
        }
      }
    }
  }
  $circle = new Shape();
  echo "Area of circle:".$circle->area(5)."</br>"; // display the area of circle
  $rect = new Shape();
  echo "Area of rectangle:".$rect->area(5,10); // display area of rectangle
?>

__call() method automatically called behind the scene.

Friday 5 April 2019

Polymorphism in PHP

Polymorphism

 This means many forms.

According to the Polymorphism, methods in different classes that do similar things should have the same name.

Example: write a classes that represent geometric shapes (such as rectangles, circles and octagons) that are different from each other in the number of sides 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.

Example, Call method that calculates the area calcArea() and put in each class that represents a 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 know about the area calculation logic for different shape.
The only thing that we would need to know is the name of the method that calculates the area.

Implement the polymorphism principle?
To implement the polymorphism, choose between abstract classes and interfaces.

Choose either abstract classes or interfaces to implement polymorphism.
Example: Create an interface named shape with calcArea() method in it.

interface Shape {
  public function calcArea();
}

Circle class implements the interface Shape by putting the formula of area calculation of circle in method calcArea().

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 interface Shape but defines the method calcArea() with formula of area calculation 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, create objects from the concrete classes:

$circ = new Circle(3);
$rect = new Rectangle(3,4);

All the above objects calculate area with the calcArea(), whether for rectangle object or circle object.

Use the calcArea() methods to calculate the area of the shapes:

echo $circ -> calcArea();
echo $rect -> calcArea();

Result:
28.274333882308
12

Interface in PHP

Interfaces - the next level of abstraction


The interface blocks which declares set of functions to be defined with a class to implement this interface.
A class can extend more than one interface.


Declare and implement an interface?
We declare an interface with the interface keyword and, a class that inherits from an interface with the implements keyword.

interface interfaceName { 
  // abstract methods
}

class Child implements interfaceName {
  // defines the interface methods and may have its own code
}

Example:  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 can have only public methods and cannot have variables. Methods in interfaces don't have body.

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; 
  }
}

Implement more than one interface in the same class?
We can implement a number of interfaces in the same 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";
  }
}


Differences between abstract classes and interfaces?

Interface supports multiple inheritance while abstract class doesn't support multiple inheritance
Interface doesn't contain constructors while abstract class contains constructors.
Interface contains only incomplete member(signature of member) while abstract class contains both incomplete(abstract) and complete member.
Interface cannot have access modifiers by default everything is assumed as public while abstract class can contain access modifiers for the subs, functions, properties.
Members of interface cannot be static while only complete member of abstract class can be static.

Thursday 28 March 2019

Abstract Class & Method

Abstract Class

  • An abstract class must be declared with an abstract keyword.
  • It can have abstract and non-abstract methods.
  • It cannot be instantiated.
  • It can have constructors and static methods also.
  • It can have final methods which will force the subclass not to change the body of the method.
Abstract classes contain one or more abstract methods. 
An abstract method is a method that is declared, but contains no implementation. 
Abstract classes may not be instantiated, and require sub-classes to provide implementations for the abstract methods.

1. Can not instantiate abstract class: Classes defined as abstract may not be instantiated, and any class that contains at least one abstract method must also be abstract.

Example below :
abstract class AbstractClass
{
  abstract protected function getValue();
  abstract protected function prefixValue($prefix);
  public function printOut() {
    echo "Hello how are you?";
  }
}

$obj = new AbstractClass();
$obj->printOut();
//Fatal error: Cannot instantiate abstract class AbstractClass

2. Any class that contains at least one abstract method must also be abstract: Abstract class can have abstract and non-abstract methods, but it must contain at least one abstract method. If a class has at least one abstract method, then the class must be declared abstract.

Note: Traits support the use of abstract methods in order to impose requirements upon the exhibiting class.

Example below :
class Non_Abstract_Class
{
   abstract protected function getValue();
   public function printOut() {
     echo "Hello how are you?";
   }
}

$obj=new Non_Abstract_Class();
$obj->printOut();
//Fatal error: Class Non_Abstract_Class contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Non_Abstract_Class::getValue)

3. An abstract method can not contain body: Methods defined as abstract simply declare the method's signature - they cannot define the implementation. But a non-abstract method can define the implementation.

abstract class AbstractClass
{
   abstract protected function getValue(){
     return "Hello how are you?";
   }
   public function printOut() {
     echo $this->getValue() . "\n";
   }
}

class ConcreteClass1 extends AbstractClass
{
  protected function getValue() {
    return "ConcreteClass1";
  }
  public function prefixValue($prefix) {
    return "{$prefix}ConcreteClass1";
  }
}

$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";
//Fatal error: Abstract function AbstractClass::getValue() cannot contain body

4. When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the child :If you inherit an abstract class you have to provide implementations to all the abstract methods in it.

abstract class AbstractClass
{
  // Force Extending class to define this method
  abstract protected function getValue();
  // Common method
  public function printOut() {
    print $this->getValue() . "<br/>";
  }
}

class ConcreteClass1 extends AbstractClass
{
  public function printOut() {
    echo "dhairya";
  }
}
$class1 = new ConcreteClass1;
$class1->printOut();
//Fatal error: Class ConcreteClass1 contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (AbstractClass::getValue)

5. Same (or a less restricted) visibility:When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the child; additionally, these methods must be defined with the same (or a less restricted) visibility. 

For example, if the abstract method is defined as protected, the function implementation must be defined as either protected or public, but not private.

Note that abstract method should not be private.

abstract class AbstractClass
{
  abstract public function getValue();
  abstract protected function prefixValue($prefix);
  public function printOut() {
    print $this->getValue();
  }
}

class ConcreteClass1 extends AbstractClass
{
  protected function getValue() {
    return "ConcreteClass1";
  }
  public function prefixValue($prefix) {
    return "{$prefix}ConcreteClass1";
  }
}
$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."<br/>";
//Fatal error: Access level to ConcreteClass1::getValue() must be public (as in class AbstractClass)

6. Signatures of the abstract methods must match: When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the child;the signatures of the methods must match, i.e. the type hints and the number of required arguments must be the same. 

For example, if the child class defines an optional argument, where the abstract method's signature does not, there is no conflict in the signature.

abstract class AbstractClass
{
    abstract protected function prefixName($name);
}

class ConcreteClass extends AbstractClass
{
    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"), "<br/>";
echo $class->prefixName("Pacwoman"), "<br/>";
//output: Mr. Pacman
//        Mrs. Pacwoman

7. Abstract class doesn't support multiple inheritance: Abstract class can extends another abstract class,Abstract class can provide the implementation of interface.But it doesn't support multiple inheritance.

interface MyInterface{
    public function foo();
    public function bar();
}

abstract class MyAbstract1{
    abstract public function baz();
}


abstract class MyAbstract2 extends MyAbstract1 implements MyInterface{
    public function foo(){ echo "foo"; }
    public function bar(){ echo "bar"; }
    public function baz(){ echo "baz"; }
}

class MyClass extends MyAbstract2{
}

$obj=new MyClass;
$obj->foo();
$obj->bar();
$obj->baz();
//output: foobarbaz

Note: Please note order or positioning of the classes in your code can affect the interpreter and can cause a Fatal error. So, when using multiple levels of abstraction, be careful of the positioning of the classes within the source code.

below example will cause Fatal error: Class 'horse' not found

class cart extends horse {
    public function get_breed() { return "Wood"; }
}

abstract class horse extends animal {
    public function get_breed() { return "Jersey"; }
}

abstract class animal {
    public abstract function get_breed();
}

$cart = new cart();
print($cart->get_breed());

Reference: https://stackoverflow.com/questions/2558559/what-is-abstract-class-in-php

Points on abstract class.
1. Declare classes and methods as abstract?
To declare a class as abstract, prefix the name of the class with the abstract keyword.

Example: abstract class Car { }

Declare abstract method with "abstract" keyword within the abstract class. Abstract method don't have body, only name and parameters inside parentheses.

Example: Create a public abstract method "calcNumMilesOnFullTank()". This method is skeleton for methods we will create in the child classes. 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();
}

If an abstract method is created in the class, the class must be abstract.

2. Can an abstract class have non abstract methods?
An abstract class can have non abstract methods. In fact, it can even have properties, and properties couldn't be abstract.

Example: Add a protected property $tankVolume and public method 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();
}

3. Create child classes from an abstract class?
Objects cannot created from abstract classes. Create child classes that inherit the abstract class code. Child class will inherit the abstract class with the help of "extends" keyword.

The child classes that inherit from abstract classes must add bodies to the abstract methods.
Example: Create a child class "Honda", define abstract method in it which is 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";
  }
}

Example: 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

Access Modifiers in PHP

Access modifiers: 

These are used to set access rights with classes and their members(methods or properties) defined within the class.

Possible Access Modifiers

Private methods or properties can only be used from inside the class. This protects members from outside class access.

Public methods or properties can be accessed from both the inside and outside of the class.

Protected modifier: which allows code usage from both inside the class and from its child classes.

Abstract: This is used only for PHP classes and its methods. An abstract class can contain abstract methods. Non abstract class can not contain abstract methods.

Final: It prevents subclasses to override parent class members with final keyword.

The public access modifier

<?php
class Car {

  // public methods and properties.
  public $model;    

  public function getModel() {
    return "The car model is " . $this -> model;
  }
}

$ferrari = new Car();
//Here we access a property from outside the class
$ferrari -> model = "Ferrari";
//Here we access a method from outside the class
echo $ferrari -> getModel();

Result: The car model is Ferrari

The private access modifier

Example, $model is private property. While trying to set its value from outside the class, we encounter a fatal error.

<?php

class Car {

  //private property
  private $model;
    
  public function getModel() {
    return "The car model is " . $this -> model;
  }
}

$ferrari = new Car();

// We try to access a private property from outside the class.
$ferrari -> model = "Ferrari";
echo $ferrari -> getModel();

Result: Fatal error: Cannot access private property Car::$model

Access a private property?

As we cannot access private properties from outside the class but still we have to set & get the properties's values.

To interact with private properties, use public methods because public methods can only interact with both the code outside as well as inside the class. These public methods are of two kinds:
Setters: This sets the value of private properties.
Getters: This gets the value of the private properties.

Example: In this example, $carModel is private property. With the use of setter and getter methods, set and get value of private property.
To set car model value use setModel() and for get car model value use getModel() method.

<?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;
  }
}

$ferrari = new Car();
//Sets the car’s model
$ferrari -> setModel("Ferrari");
//Gets the car’s model
echo $ferrari -> getModel();

Result: The car model is Ferrari

Why we need access modifiers?

To limit the modifications to class's methods and properties done by the code outside of the class.
When we define any method or property as private, only methods within the class can use these private methods or properties. So to interact with private methods and properties, we need to create public methods. Inside these public methods, put your logic to validate and restrict data that comes from outside of the class.

In our example, we can validate that only certain car models can make their way, and be assigned to the private $model property, 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 property 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", "Ferrari");

    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;
  }
}


$ferrari = new Car();
//Sets the car’s model
$ferrari -> setModel("Ferrari");
//Gets the car’s model
echo $ferrari -> getModel();