Validating User Input with the Strategy Pattern

The strategy design pattern is applied much more often than you might think, so if you want to find out how to implement it with PHP 5, this article should guide you through the whole learning process. Welcome to the final installment of the series that began with “Introducing the Strategy Pattern.” In two parts, this series walks you through the key points of how the strategy pattern works, and accompanies its theoretical concepts with copious hands-on examples.

Introduction

Going back quickly to the topics covered in the first tutorial of the series, certainly you’ll remember that I explained the foundations of the strategy design pattern, and complemented the theory with some practical examples of how to apply this handy pattern in PHP 5.

Based upon this scenario, I developed a set of simple PHP classes. One of them was defined as a strategy selector, handy for determining what type of format (HTML or XML) had to be applied to certain file data. The other ones were tasked with implementing a given formatting strategy.

Although the example that I just described may seem rather basic, it shows in a nutshell the logic that drives the strategy pattern: on one hand there’s a class that sets the context as to where a predefined group of strategies will be applied, while on the other hand there’s one or more classes that implement  these strategies.

However, now that you hopefully digested the contents of the first article of the series, let me tell you what you’ll learn in this final tutorial. In the next few lines I’m going to demonstrate how to use the strategy pattern in a useful case, that is validating user-supplied input. Sound like an interesting experience, right?

Now that you know the purpose of this last part of the series, let me show you how to implement the strategy pattern to check a wide range of user inputs. Let’s begin now!

{mospagebreak title=Building a validation strategy selector}

In consonance with the concepts that I expressed in the beginning, my objective here is to demonstrate how the strategy pattern can help to create a data validation system capable of verifying different types of user data.

Bearing in mind this important requisite, the first step that I’m going to take will consist of building a validation strategy selector (naturally, represented by a PHP class) which will determine what validation strategy must be applied, in accordance with the type of data submitted by a user.

That being said, the validation strategy selector looks like this:

// define ‘ValidationStrategySelector’ class
class ValidationStrategySelector{
   private $strategy=NULL;
   public function __construct($strategy){
     if($strategy!=’alpha’&&$strategy!=’alphanum’&&$strategy!
=’number’&&$strategy!=’email’){
       throw new Exception(‘Invalid parameter for validation
strategy!’);
     }
     switch($strategy){
       case "alpha": 
         $this->strategy=new StrategyAlphabetic();
         break;
       case "alphanum": 
         $this->strategy=new StrategyAlphanumeric();
         break;
       case "number": 
         $this->strategy=new StrategyNumber();
         break;
       case "email": 
         $this->strategy=new StrategyEmail();
         break;
     }
   }
   public function validateData($inputData){
     if(!$this->strategy->validateData($inputData)){
       return ‘Input data is not valid!’;
     }
     return ‘Input data is OK!’;
   }
}

As you can see, the above strategy selector accepts the type of validation strategy, that is the "$strategy" parameter, as its unique input parameter. Next, according to the value of this variable, a specific strategy class is properly instantiated to validate a huge variety of data types, including alphabetic and alphanumeric data, as well as numbers and email addresses.

Actually, the logic that stands behind the strategy pattern is demonstrated by the other method that belongs to the previous class, in this case the one called "validateData()," since it takes care of using the proper strategy to validate a specific type of data. So far, the signature of the above class look really simple, right?

Okay, at this stage I’m sure that you understand how the prior validation strategy selector works. Nevertheless, as you saw, the class in question creates four different strategy objects in turn, in accordance with the type of data being verified.

Therefore, it’s obviously necessary to show the respective signatures for these strategy classes, so you can see more clearly how they’re capable of performing different validation on user-supplied data.

As you may have guessed, defining all these new classes is something that will be covered in the following section. So please click on the link that appears below and keep reading.

{mospagebreak title=Building some strategy classes}

As you’ll certainly recall from the previous section, the validation strategy selector spawns four different objects, and each one of them is responsible for validating a specific type of data. Therefore, taking this situation into account, below I listed the respective signatures corresponding to these strategy classes.

Here they are, so have a look at them, please:

// define ‘StrategyAlphabetic’ class
class StrategyAlphabetic{
   public function validateData($inputData){
     if(!$inputData||!preg_match("/^[a-zA-Z]+$/",$inputData)){
       return false;
     }
     return true;
   }
}
// define ‘StrategyAlphanumeric’ class
class StrategyAlphanumeric{
    public function validateData($inputData){
      if(!$inputData||!preg_match("/^[a-zA-Z0-9]
+$/",$inputData)){
        return false;
      }
      return true;
    }
}
// define ‘StrategyNumber’ class
class StrategyNumber{
   public function validateData($inputData){
     if(!$inputData||!is_numeric($inputData)){
       return false;
     }
     return true;
   }
}
// define ‘StrategyEmail’ class
class StrategyEmail{
   public function validateData($inputData){
     if(!$inputData||!preg_match("/.+@.+..+./",$inputData)||!
checkdnsrr(array_pop(explode("@",$inputData)),"MX")){
       return false;
     }
     return true;
   }          
}

As shown above, each of the four strategy classes listed previously implements differently the same "validateData()" method to check a diverse range of user inputs, such as alphabetic and alphanumeric values, and number and email addresses.

Of course, it’s possible to extend the initial validation capacity of the whole data checking system even more, simply by adding new strategy classes to the existing ones. This is definitely a process that can be performed with minor hassles.

So far, so good. At this point, you’ve seen not only how the validation strategy selector looks, but how the four strategy classes have been properly defined. This is very convenient for understanding the schema imposed by the strategy pattern.

So, the question that comes up is: what’s the next step now? Well, considering that you already grasped the logic implemented by all the classes that I defined so far, it’s time to move forward and see a concrete example where a data validation system is created by using the aforementioned classes.

Want to see how the strategy pattern is applied to validate user-supplied input? Jump straight into the following section and keep reading.

{mospagebreak title=Validating user-supplied data}

To demonstrate how all the classes that you learned in previous sections of this tutorial can be used to check the validity of different types of data, below I coded a short script that shows some illustrative cases where the validation strategy selector verifies firstly alphabetic and alphanumeric values, and lastly numbers and email addresses.

Having said that, the corresponding examples look like this:

try{
   // example using the ‘Strategy pattern’
   $strategyAlpha=new ValidationStrategySelector(‘alpha’);
   echo $strategyAlpha->validateData(123);
   /* displays the following:
   Input data is not valid!
   */
   $strategyAlphanum=new ValidationStrategySelector(‘alphanum’);
   echo $strategyAlphanum->validateData(‘ABC123′);
   /* displays the following
   Input data is OK!
   */
   $strategyNumber=new ValidationStrategySelector(‘number’);
   echo $strategyNumber->validateData(‘ABC’);
   /* displays the following:
   Input data is not valid!
   */
   $strategyEmail=new ValidationStrategySelector(‘email’);
   $strategyEmail->validateData(‘inexistent-user@domain.com’);
   /* displays the following:
   Input data is not valid!
   */         
}
catch(Exception $e){
   echo $e->getMessage();
   exit();
}

As you can see, the prior examples illustrate in a step-by-step format how the strategy design pattern can be used in a real situation, in this particular case, aimed at validating a wide variety of data types.

As you saw, the first two examples use the validation strategy selector to verify alphabetic and alphanumeric values in turn, and also display the respective results. Finally, the other two cases demonstrate how to use the same selector to validate numeric data and an email address.

All right, I believe that all these examples should give you an approximate idea of how the strategy pattern can be used in a real-world situation. In the last section of this tutorial I’m going to list all the classes that you learned here. By doing so, you’ll have available at one single place the complete source code required to implement the strategy pattern in PHP 5.

As you know, the last section of this article is just one click away, so go forward and keep reading.

{mospagebreak title=Listing all the classes required to implement the strategy pattern}

As I promised before, here are all the classes that I built over the course of this tutorial to apply the strategy pattern with PHP 5:

// define ‘ValidationStrategySelector’ class
class ValidationStrategySelector{
   private $strategy=NULL;
   public function __construct($strategy){
     if($strategy!=’alpha’&&$strategy!=’alphanum’&&$strategy!
=’number’&&$strategy!=’email’){
       throw new Exception(‘Invalid parameter for validation
strategy!’);
     }
     switch($strategy){
       case "alpha": 
         $this->strategy=new StrategyAlphabetic();
         break;
       case "alphanum": 
         $this->strategy=new StrategyAlphanumeric();
         break;
       case "number": 
         $this->strategy=new StrategyNumber();
         break;
       case "email": 
         $this->strategy=new StrategyEmail();
         break;
     }
   }
   public function validateData($inputData){
     if(!$this->strategy->validateData($inputData)){
       return ‘Input data is not valid!’;
     }
     return ‘Input data is OK!’;
   }
}
// define ‘StrategyAlphabetic’ class
class StrategyAlphabetic{
   public function validateData($inputData){
     if(!$inputData||!preg_match("/^[a-zA-Z]+$/",$inputData)){
       return false;
     }
     return true;
   }
}
// define ‘StrategyAlphanumeric’ class
class StrategyAlphanumeric{
   public function validateData($inputData){
     if(!$inputData||!preg_match("/^[a-zA-Z0-9]+$/",$inputData)){
       return false;
     }
     return true;
   }
}
// define ‘StrategyNumber’ class
class StrategyNumber{
   public function validateData($inputData){
     if(!$inputData||!is_numeric($inputData)){
       return false;
     }
     return true;
   }
}
// define ‘StrategyEmail’ class
class StrategyEmail{
   public function validateData($inputData){
     if(!$inputData||!preg_match("/.+@.+..+./",$inputData)||!
checkdnsrr(array_pop(explode("@",$inputData)),"MX")){
       return false;
     }
     return true;
   }          
}

That’s it. As usual with all my articles, feel free to modify the signature of all the classes that I showed here so you can acquire a better understanding of this pattern. Have a good time!

Final thoughts

Unfortunately, we’ve come to the end of this series. However, I hope that after reading these two articles, you’ll have a better idea not only of how the strategy pattern works, but how it can be used in real situations.

See you in the next PHP tutorial!

[gp-comments width="770" linklove="off" ]
antalya escort bayan antalya escort bayan