Home arrow PHP arrow Page 2 - Using Multiple Strategy Classes with the Strategy Design Pattern

Review: the example classes developed so far - PHP

Being one of the most popular contenders in the exciting, but very often complex, terrain of software design, the Strategy design pattern is a well-trusted paradigm. It allows you to build more flexible and efficient applications by appealing to the functionality of two of the big pillars of solid object-oriented programming: favoring Composition over Inheritance, and encapsulating the concepts that vary. This is the conclusion to a six-part series that shows you how to use the Strategy design pattern to validate incoming data.

TABLE OF CONTENTS:
  1. Using Multiple Strategy Classes with the Strategy Design Pattern
  2. Review: the example classes developed so far
  3. The Strategy pattern in action
  4. Setting up a different validation strategy
By: Alejandro Gervasio
Rating: starstarstarstarstar / 2
April 28, 2010

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

As always, before I get my hands dirty and show how to build a flexible program that permits us to create different validation strategies at run time using all of the classes built in previous installments of the series, it'd be useful to recall how these classes looked.

So first, here's the definition of a trivial form helper. Via its "addValidator()" method, it will take a predefined set of data checking objects, handy for setting up different validation strategies on the fly. Take a peek at it:

(FormHelper.php)

<?php

class FormHelper

{

    protected $_validators = array();

    protected $_errors = array();

   

    // add a validator

    public function addValidator(AbstractValidator $validator)

    {

        $this->_validators[] = $validator;

        return $this;

    }

   

    // get all the validators

    public function getValidators()

    {

        return !empty($this->_validators) ? $this->_validators : null;

    }

     

    // validate inputted data

    public function validate()

    {

        $validators = $this->getValidators();

        if (null !== $validators)

        {

            foreach ($validators as $validator)

            {

                if (!$validator->validate())

                {

                    $this->_errors[] = $validator->getFormattedError();

                }

            } 

        }

        return empty($this->_errors) ? true : false;

    }

   

    // get validation errors as an array

    public function getErrors()

    {

        return $this->_errors;

    }

   

    // get validation errors as a string

    public function getErrorString()

    {

        $errors = $this->getErrors();

        return !empty($errors) ? implode('', $errors) : '';

    }

   

    // clear state of the form helper

    public function clear()

    {

        $this->_validators = array();

        $this->_errors = array();

    }  

}

As you can see, the "FormHelper" class behaves like a container that houses different validation objects eventually injected via its "addValidator()" method. Once these objects are stored on the protected $_validators property, they're used internally to check whether or not the supplied data is valid. Of course, you'll understand the inner workings of this process much better when I show you a functional example, so pay attention to the following class, which defines the structure and behavior of generic validation objects:     

(AbstractValidator.php)

<?php

abstract class AbstractValidator

{

    protected $_value = '';

    protected $_filter = '';

    protected $_options = null;

    protected $_errorMessage = '';

    protected $_errorPrefix = '<p>';

    protected $_errorSufix = '</p>';

   

    // constructor

    public function __construct($value, array $options = null)

    {

        $this->_value = $value;

        if (null !== $options)

        {

           $this->setOptions($options);

        }

    }

   

    // get supplied value

    public function getValue()

    {

        return $this->_value;

    }

   

    // set validation options

    public function setOptions(array $options)

    {

        if (empty($options))

        {

            throw new ValidatorException('Invalid options for the validator.');

        }

        $this->_options = $options;

    }

   

    // get validation options

    public function getOptions()

    {

        return $this->_options;

    }

     

    // set the validation filter

    public function setFilter($filter)

    {

        if (!is_string($filter))

        {

            throw new ValidatorException('Invalid filter for the validator.'); 

        }

        $this->_filter = $filter;

    }

   

    // get the validation filter

    public function getFilter()

    {

        return $this->_filter;

    }

   

    // set the error message

    public function setErrorMessage($errorMessage)

    {

        if (!is_string($errorMessage))

        {

            throw new ValidatorException('Invalid error message for the validator.');    

        }

        $this->_errorMessage = $errorMessage;

    }

   

    // get error message

    public function getErrorMessage()

    {

        return $this->_errorMessage;

    }

              

    // get formatted error string

    public function getFormattedError()

    {

        return $this->_errorPrefix . 'The value ' . $this->getValue() . ' is incorrect. ' . $this->getErrorMessage() . $this->_errorSufix;

    }

   

    // validate the supplied value 

    public function validate()

    {

        return filter_var($this->getValue(), $this->getFilter(), $this->getOptions());  

    }

}

(ValidatorException.php)

<?php

class ValidatorException extends Exception{}

As you can see, this class validates a value passed to its constructor by using a specific PHP filter. This can be easily understood by analyzing the implementation of the class' "validate()" method, which is merely a proxy for the built-in PHP "filter_var()" function.

Do you understand the logic behind this abstract validator? Great. Now, take a look at the following concrete classes, which are refined implementations of their abstract parent and can be used for checking integers, float numbers, email addresses and URLs by simply overriding a couple of inherited properties. Here they are:  

(IntegerValidator.php)

<?php

class IntegerValidator extends AbstractValidator

{

    protected $_filter = FILTER_VALIDATE_INT;

    protected $_errorMessage = 'Please enter an integer value.';

}

(FloatValidator.php)

<?php

class FloatValidator extends AbstractValidator

{

    protected $_filter = FILTER_VALIDATE_FLOAT; 

    protected $_errorMessage = 'Please enter a float value.';

}

(EmailValidator.php)

<?php

class EmailValidator extends AbstractValidator

{

    protected $_filter = FILTER_VALIDATE_EMAIL; 

    protected $_errorMessage = 'Please enter a valid email address.';

}

(UrlValidator.php)

<?php

class UrlValidator extends AbstractValidator

{

    protected $_filter = FILTER_VALIDATE_URL; 

    protected $_errorMessage = 'Please enter a valid URL.';

}

 

Done. At this point it's clear to see that defining concrete subclasses that can be used for validating a specific type of data is a breeze. Of course, I could go on and on creating more validators, but that would be a waste of time, as the four we have now are enough to demonstrate how to set up distinct validation strategies at run time.

Now that we've reviewed all of the sample classes developed so far, the next step is to put these elements to work together. This way you can see how easy it is to validate incoming data using the set of strategy classes just analyzed.

This will be done in the coming section. So click on the link below and keep reading.



 
 
>>> More PHP Articles          >>> More By Alejandro Gervasio
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PHP ARTICLES

- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: