A PHP Developer's Blog - Joakim Nygård

About jokke.dk

jokke.dk is the personal website of , a software architect, entrepeneur and Mac user living in Copenhagen, Denmark.

Search the Site

Recent Posts

Popular Posts

Zend Framework Validator for Danish VAT Numbers

17th March, 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.

« New Music In February  –  Scienta ZF Debug Bar 1.4 »