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.