Zend Framework Validator for Danish VAT Numbers
17 Mar 2009
Working on an as of yet unpublished startup, I needed a validator for the Danish CVR numbers issued as part of VAT registration. As the project is written in Zend Framework, I decided to implement the code as an extension of the Zend_Validate_Abstract and share it here.
The validation is based on the specification located at cvr.dk and involves a modulus 11 check on the 8th digit based on a weighted sum of the previous seven. Not particularly interesting but nice to have when working with Danish companies.
<?php
/**
* Scienta Zend Additions
*
* @category Scienta
* @package Scienta_Validate
* @copyright Copyright (c) 2008-2009 Joakim Nygård (http://jokke.dk)
* @version $Id$
*/
/** Zend_Validate_Abstract */
require_once 'Zend/Validate/Abstract.php';
/** Zend_Filter_Digits */
require_once 'Zend/Filter/Digits.php';
/**
* A class for validating Danish CVR numbers based on modulo 11
* @see http://www.cvr.dk/Site/Forms/CMS/DisplayPage.aspx?pageid=60
* @category Scienta
* @package Scienta_Validate
* @copyright Copyright (c) 2008-2009 Joakim Nygård (http://jokke.dk)
*/
class Scienta_Validate_Cvr extends Zend_Validate_Abstract
{
const INVALID = 'cvrInvalid';
const INCORRECT_LENGTH = 'stringLengthNotRight';
const NOT_DIGITS = 'notDigits';
protected $_messageTemplates = array(
self::INVALID => "'%value%' is not a valid CVR number",
self::INCORRECT_LENGTH => "'%value%' does not contain 8 digits",
self::NOT_DIGITS => "'%value%' does not contain only digits",
);
protected $_cvrWeights = array(2, 7, 6, 5, 4, 3, 2);
public function isValid($value)
{
$valueString = (string) $value;
$this->_setValue($valueString);
$filter = new Zend_Filter_Digits();
if ($valueString !== $filter->filter($valueString)) {
$this->_error(self::NOT_DIGITS);
return false;
}
if (8 != strlen($valueString)) {
$this->_error(self::INCORRECT_LENGTH);
return false;
}
$sum = 0;
foreach ($this->_cvrWeights as $i => $weight) {
$sum += $valueString[$i] * $weight;
}
$remainder = $sum % 11;
if($remainder==1){
$this->_error(self::INVALID);
return false;
}
if($remainder==0)
$lastDigit = 0;
else
$lastDigit = 11 - $remainder;
$valid = ($valueString[7] == $lastDigit);
if ($valid) {
return true;
} else {
$this->_error(self::INVALID);
return false;
}
}
}
Save the above to the file library/Scienta/Validate/Cvr.php
with library being the directory containing the Zend framework. The class can then be used to test a number as follows:
$cvrValidator = new Scienta_Validate_Cvr();
if ($cvrValidator->isValid($proposedCvrNumber)) {
...
}
One case where testing is needed might be a Zend_Form, in which case the class is easily added as a validator on the appropriate element.