This is the third and last part o the explanation of how to implement a csv file validation in php, using the Strategy Pattern.
If you remember the first post, we started implementing simple validations for each column, and in the second post, we wrote the main class that will take care of processing the whole CSV file.
Now, it’s time to implement the missing piece, to merge both parts. Basically, we need a class that should act as interface between our analyzer and the validators. We should apply a different validation’s implementation depending on the csv field.
In order to do that, I turn the field’s name into the class name that should take care of the validation of the field. In example, if the field is called “short_description”, then its validator class should be ShortDescription (UpperCamelCase). In order to separate the validators by phases, I prepend the phase with an underscore, so for instance, the previous example would eventually be Lexical_ShortDescription and Semantic_ShortDescription.
Then, all I have to do is instantiate the class, and call its method “validate” with the given input, and return the result.
This how it looks like:
class ValidatorContext { private $strategy; private $warnings; /* * Create the instance of the validator by building the class name with the UpperCamelCase format * Generate a warning if the validator wasn't found, and create a generic validator instance * * @param $type string type of analysis * @param $strategy string validator strategy class name * @param $optData array optional data passed to the semantic validators * @return void */ function __construct($type, $strategy, $profile, $optData = null) { $this->warnings = array(); $validator = ucfirst($type) . '_' . str_replace(' ', '', ucwords(str_replace('_', ' ', $validator))); if(class_exists($validator)) { $this->strategy = new $validator($profile, $optData); }else { $this->strategy = new Generic_Validator(); $this->warnings[] = sprintf('Strategy %s (%s) is not implemented for the %s analizer ' . "\n", $strategy, $validator, $type); } } /** * Remove elements from memory * @return void */ function __destruct() { unset($this->strategy); } /** * getTokens * Return the tokens retrieved from the validator * @return array */ public function getTokens() { return $this->strategy->getTokens(); } /** * getErrors * Return the errrors found during the validation * @return array */ public function getErrors() { return $this->strategy->getErrors(); } /** * getWarnings * Return the warnings found during the validation * @return array */ public function getWarnings() { return $this->warnings; } /** * getErrorMsg * Return the errror description to help the user to solve the problem * @param $input string|array * @return string */ public function getErrorMsg($input) { return $this->strategy->getErrorMsg($input); } /** * validate * @access public * @param $input mixed input data of the csv * @return bool whether this data is valid or not for current validator */ public function validate(&$input) { //Uncomment the line below to debug //echo get_class($this->_strategy) . ": " . $input . "\n"; return $this->strategy->validate($input); } }
And basically, that’s about it. You might thrown an exception if there is no validation found for a certain field, but in my case its enough to just bypass the validation, so the Generic_Validator class, will always return true.
I hope this can help you to implement your own csv validation in php. If you want to download the source code of the whole application, I’ll put the link with some working examples of usage included during this week.
Updated on 14/04/2013
I’ve created a git repository with the source code of the CSV validator. I’ve included an example of usage with some demo files as well. All you have to do is clone the repository and execute “example.php” from php-cli.
You get the source code of the validator from here.