Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate valid EAN13 in PHP

Tags:

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);
}
like image 708
Flash Thunder Avatar asked Nov 10 '13 13:11

Flash Thunder


3 Answers

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.

like image 69
GolezTrol Avatar answered Sep 26 '22 12:09

GolezTrol


I think it is better to change the above code to the following, because the EAN value for both 7 and 70 (and so on) numbers will be the same.

$code = '200' . str_pad($number, 9, '0', STR_PAD_LEFT);

Thanks, Mansour

like image 36
Mansour Avatar answered Sep 24 '22 12:09

Mansour


I came onto this answer because I was looking for a random EAN generator that generates radnom EAN's, that are valid. On the basis of the answer of GolezTrol, I made this. Maybe it can help someone:

        function generateEAN()
{
    $date = new DateTime();
    $time = $date->getTimestamp();

    $code = '20' . str_pad($time, 10, '0');
    $weightflag = true;
    $sum = 0;

    for ($i = strlen($code) - 1; $i >= 0; $i--) {
        $sum += (int)$code[$i] * ($weightflag ? 3 : 1);
        $weightflag = !$weightflag;
    }
    $code .= (10 - ($sum % 10)) % 10;
    return $code;
}

This generates a unique EAN because it uses the UNIX TIMESTAMP. So: each second a new, unique, valid EAN can be generated. This is for me (for use in a simple enironment where one new EAN per second will do) perfect

like image 45
Lect Avatar answered Sep 25 '22 12:09

Lect