Wednesday, 9 May 2012

Implementing polymorphism using the Strategy Design Pattern in PHP

The Strategy pattern is used to separate an object from its algorithms. The core idea of the pattern is the OOP principal of polymorphism. More explicitly, a Strategy pattern is a group of algorithms encapsulated inside classes that are made interchangeable so the algorithm can vary depending on the class used. Strategies are useful when you would like to decide at run time when to implement each algorithm. They can be used to vary each algorithm’s usage by its context.
The Strategy pattern has three main components: the Strategy, the Concrete Strategy, and the Context. The strategy is a common interface that ties together all supported algorithms. Usually this class is abstract. The concrete strategy is the implementation class where the logic for each different algorithm lives in the group. The context is the object that ties a concrete strategy to a particular code flow.


Advantage of the strategy pattern
As mentioned earlier, the motive behind the strategy pattern is to separate an object from its algorithms. Removing the algorithms from the host class and putting them in a separate class, enables the host to concentrate on its own job. Otherwise, the host will get messy with all the algorithms in itself with lot of if-else or switch-case statements.
Here’s an example.
Suppose a car renting service charges its customers differently at different situations – sometimes based on kilometers travelled, sometimes on hours of travel, and sometimes on a combination of both, depending on festive seasons, off-seasons etc.
There’s a billing class in the application which prepares the bill for the customer. Now the payable amount part needs a lot of calculations based on the type of charge, distance and hours of travel resulting in a lot of if-else or case statements. Addition of more billing algorithms results in inclusion of more if-else statements. To make the situation better, we simply encapsulate each faring algorithm in a separate class and depending on the context at runtime, we decide which algorithm to choose. Addition of another faring algorithm is done by simply adding another class i.e. extending the abstract class FareStrategy.

<?php
abstract class FareStrategy
{
    abstract function calculateFare($kms, $hrs);
}

class HourlyFareStrategy extends FareStrategy
{
    private $normalHours=8;
    private $normalHourRate=250;
    private $additionalHourRate=200;
   
    function calculateFare($kms, $hrs)
    {
        if($hrs > $this->normalHours)
        {
            $fare=($this->normalHours*$this->normalHourRate)+(($hrs-$this->normalHours)*$this->additionalHourRate);
            return $fare;
        }
        else
        {
            $fare=$hrs*$this->normalHourRate;
            return $fare;
        }       
    }
} //end class HourlyFareStrategy

class KmsFareStrategy extends FareStrategy
{
    private $normalKms=100;
    private $normalKmRate=15;
    private $additionalKmRate=13;
   
    function calculateFare($kms, $hrs)
    {
        if($kms>$this->normalKms)
        {
            $fare=($this->normalKms*$this->normalKmRate)+(($kms-$this->normalKms)*$this->additionalKmRate);
            return $fare;
        }
        else
        {
            $fare=$kms*$this->normalKmRate;
            return $fare;
        }
    }
}//end class KmsFareStrategy

class FaringContext
{
    private $_fareStrategy;
   
    public function __construct(FareStrategy $fareStrategy)
    {
        $this->_fareStrategy=$fareStrategy;
    }
   
    public function getFare($kms,$hrs)
    {
        return $this->_fareStrategy->calculateFare($kms,$hrs);
    }
} //end class FaringContext

//main program

$context=new FaringContext(new HourlyFareStrategy());
$fare=$context->getFare(120,6);
echo $fare;

echo '<br />';

$context=new FaringContext(new KmsFareStrategy());
$fare=$context->getFare(120,6);
echo $fare;

?>

Wednesday, 18 April 2012

Simple pagination class in PHP

File: paginator.php
 
<?php
require_once 'DB.php';

class Paginator
{
    private $queryStr;
    private $pageSize;
    private $currentPage=1;
    private $conn;
    private $totalRecords;
    private $totalPages;
   
    public function __construct($queryStr,$pageSize,$totalRecords)
    {
        $this->conn=DB::db_connect();
        $this->queryStr=$queryStr;
        if(isset($_REQUEST['showpage']))
        $this->currentPage=$_REQUEST['showpage'];
        $this->pageSize=$pageSize;
        $this->totalRecords=$totalRecords;
        $this->totalPages=ceil(($this->totalRecords)/($this->pageSize));
    }
   
    public function getPage()
    {
        $offset=($this->currentPage-1)*($this->pageSize);
        $queryStr="$this->queryStr limit $offset,$this->pageSize";   
        $result=$this->conn->query($queryStr);
        return $result;               
    }
   
    public function showNavigationLinks()
    {
        echo "<div id='nav'>";
       
        if($this->currentPage>1)
        {
            echo "<a href=index.php?showpage=".($this->currentPage-1).">Prev</a>";
        }
       
        echo "&nbsp";
       
        for($i=1;$i<=$this->totalPages;$i++)
        {
            echo "<a href=index.php?showpage=".$i.">".$i."</a>&nbsp";
        }
       
        echo "&nbsp";
       
        if(($this->totalRecords)>($this->currentPage)*($this->pageSize))
        {
            echo "<a href=index.php?showpage=".($this->currentPage+1).">Next</a>";
        }
       
        echo "</div>";
       
    }
   
}

?>

File: DB.php

<?php

class DB
{
    public static function db_connect()
    {
       $result = new mysqli('localhost', 'root', '', 'test');
       if (!$result)
          return false;
       return $result;
    }   

}

?>

File: index.php

<?php

require_once 'paginator.php';
require_once 'DB.php';

//I have a table 'countries' having two fields id, name

$mainquery='Select * from countries';
$countquery='Select count(id) as rec_count from countries';
$conn=DB::db_connect();
$result=$conn->query($countquery);
$row=$result->fetch_object();
$totalRecords=$row->rec_count;



$pg=new Paginator($mainquery,6,$totalRecords);
$pageData=$pg->getPage();

while($row=$pageData->fetch_object())
{
    echo '<br />'.$row->id.'-'.$row->name;   
}
echo '<br />';
$pg->showNavigationLinks();

?>

Monday, 16 April 2012

Using bitwise operators to assign permission levels of users

Bitwise operators if tactfully used can be very efficient in storing permission levels of users in an application. Notice there is something special about the numbers 1, 2, 4, 8 and 16. In each of these values the left- most 1 - bit advances a placeholder. These are powers of 2 (20=1, 21 =2, 22 =4, 23 =8, 24 =16 and so forth). This is the reason why they can be used as the integer values for the permission constants.

For eg., let the permissions be

1 = 0000 0001 for READ,
2 = 0000 0010 for CREATE,
4 = 0000 0100 for UPDATE,
8 = 0000 1000 for DELETE

This means, permissions of READ and UPDATE both would be specified by turning the 1st and 3rd bits on from the right, i.e., 0000 0101, which we can get by applying bitwise ‘or’ on 1 and 4.
1 |4 = 5 = 0000 0101.

<?php

class User
{
 //Permission levels
   const READ=1;
   const CREATE=2;
   const UPDATE=4;
   const DELETE=8;
     
   public $name;
   public $permission;
     
   public function addPermission($perm)
   {
     $this->permission=$perm;
   }
     
   public function removePermission($perm)
   {
     $this->permission = ~$perm & $this->permission;
   }
     
   public function showDetails()
   {
     echo '<br />';
     echo $this->name;
     echo ($this->permission & self::READ)? '<br />READ - YES':'<br />READ - NO';
     echo ($this->permission & self::CREATE)? '<br />CREATE - YES':'<br />CREATE - NO';
     echo ($this->permission & self::UPDATE)? '<br />UPDATE - YES':'<br />UPDATE - NO';
     echo ($this->permission & self::DELETE)? '<br />DELETE - YES':'<br />DELETE - NO';
    }
     
}

$user=new User();
$user->name='Barun Samanta';

$user->addPermission(User::READ|User::CREATE);
$user->showDetails();

$user->removePermission(User::CREATE);
$user->showDetails();

?>

In the code, to see if the user has been granted a particular permission, just mask out the value you are looking for with bitwise-and.

$this->permission & self::CREATE

Since in the CREATE permission all bits are zeros except the 2nd one from the right, therefore the result of the operation ($this->permission & self::CREATE) would evaluate to true if the 2nd bit from right in $this->permission
is 1 and false if the same bit is 0.

To remove a permission we apply ~$perm & $this->permission.
This means, if the permission we want to remove be UPDATE (0000 0100) from the permission set 0000 0101 (READ, UPDATE) we apply a bitwise AND of ~0000 0100 = 1111 1011 on 0000 0101. We get 0000 0001 as result. In the number 1111 1011, since all the bits are 1 except the 3rd from the right, the bitwise-and operation simply turns-off the bit for UPDATE keeping all other bits in the permission-set 0000 0101 unchanged.



Note: To store the permission in the MySQL database, simply use a column of type int(10) unsigned.

Friday, 2 March 2012

Database connection using the Singleton pattern

The Singleton is, probably, the simplest design pattern. Its goal is to provide access to a single resource that is never duplicated, but that is made available to any portion of an application that requests it without the need to keep track of its existence. The most typical example of this pattern is a database connection, which normally only needs to be created once at the beginning of a script and then used throughout its code. With the singleton pattern, an object is instantiated when you first call for it (known as lazy loading); from that point on, each call will return the same object.

Here’s an example how to use this pattern in PHP in a database connection:

<?php

class DB
{
       private static $_instance=NULL;
       private function __construct()
       {
          self::$_instance=new mysqli('localhost', 'root', '', 'test');       
       }
      
       public static function getInstance()
       {
              if(self::$_instance == NULL)
              {
                     new DB();
              }
              return self::$_instance;
       }
}

?>

To use the singleton, because static methods are accessible within the global scope, wherever we want a database connection, we can simply call DB::getInstance().

$connection=DB::getInstance();

document.write() overwrites the entire page

document.write is a function which basically outputs whatever is given to it. But sometimes, improper usage may overwrite the entire page d...