Flash Thunder Flash Thunder - 6 months ago 30
PHP Question

Generate valid EAN13 in PHP

There are alot of classes to generate barcode image, but I can't find a function that would create valid EAN13 number. Internal numbers should start with 200 ... how do I generate a valid EAN13 number that would be next valid EAN to given value?

Validation function looks like this:

function ean13_check($digits){
if($digits <= 0) return 0;
while(strlen($digits) < 13){
$digits = '0'.$digits;
}
$digits=preg_split("//",$digits,-1,PREG_SPLIT_NO_EMPTY);
$a=$b=0;
for($i=0;$i<6;$i++){
$a+=(int)array_shift($digits);
$b+=(int)array_shift($digits);
}
$total=($a*1)+($b*3);
$nextten=ceil($total/10)*10;
return $nextten-$total==array_shift($digits);
}

Answer

Like you said, 200 (actually the entire 200 - 299 range) is a fake country code that indicates that the number is an internal number. That means that you can make up the rest of the number.

An EAN number is typically 13 digits long, although it can have other lengths as well. Let's keep it at 13, since you specified the want for EAN13.

The 13th digit is a check digit. So all you have to do, is perform the same validation but with a twist. Instead of calculating the check digit and validate if the last digit matches the check digit, you just calculate the check digit and add it to the 12 digits you already have.

I haven't really tried to modify your existing code, since it looks confusing and complex, but based on the validation rules I found on Wikipedia, this should do the trick:

function generateEAN($number)
{
  $code = '200' . str_pad($number, 9, '0');
  $weightflag = true;
  $sum = 0;
  // Weight for a digit in the checksum is 3, 1, 3.. starting from the last digit. 
  // loop backwards to make the loop length-agnostic. The same basic functionality 
  // will work for codes of different lengths.
  for ($i = strlen($code) - 1; $i >= 0; $i--)
  {
    $sum += (int)$code[$i] * ($weightflag?3:1);
    $weightflag = !$weightflag;
  }
  $code .= (10 - ($sum % 10)) % 10;
  return $code;
}

$number is the internal code you want to have EANed. The prefix, zero-padding and checksum are added by the function.