PHP port of ISBN-10/13 tool

OSS4Lib and David Bigwood (Catalogablog) wrote the other day about an ISBN tool from ManaSystems that converts ISBN-10 to ISBN-13. ManaSystem’s version is written in Perl, so I went ahead and ported it to PHP5 for the rest of us.

Feel free to download it here, or from my files section.

Basically, all the function names are the same, so the original instructions apply. From the ISBN.pl page:

convert($isbn)
Takes a 10 digit ISBN and returns the 13 digit equivalent. Does not perform any error checking or validation.

gettype($isbn)
Takes a string value and will make a guess as to whether or not it fits the criteria of an ISBN. Returns 10 for a possible ISBN-10 and 13 for ISBN-13. Does not validate further.

validateten($isbn)
Takes a 10 digit numeric value and checks to determine if it is a valid ISBN-10.

validatettn($isbn)
Takes a 13 digit digit numeric value and checks to determine if it is a valid ISBN-13.

genchksum13($isbn)
Takes a 12 digit numeric value and generates an ISBN-13 checksum digit.

genchksum10($isbn)
Takes a 9 digit numeric value and generates an ISBN-10 checksum digit.

printinvalid() Returns a message informing the user the ISBN is invalid.

Of course, you’ll instantiate it a little differently:

<?php
require_once('ISBN.php');
 
$isbn_no = "012345678";
$ISBN = new ISBN;
$isbntype = $ISBN->gettype($isbn_no);
 
if ($isbntype < 1) { $ISBN->printinvalid(); }
else if ($isbntype == 10) { $isvalidten = $ISBN->validateten($isbn_no); }
else if ($isbntype == 13) { $isvalidttn = $ISBN->validatettn($isbn_no); }
 
if ($isvalidten) { print "That is a valid ISBN-10\n"; } 
else if ($isvalidttn) { print "That is a valid ISBN-13\n"; } 
else { $ISBN->printinvalid(); }
?>

Enjoy!

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • blinkbits
  • blogmarks
  • co.mments
  • del.icio.us
  • De.lirio.us
  • digg
  • Furl
  • LinkaGoGo
  • Ma.gnolia
  • scuttle
  • Shadows
  • Simpy
  • TailRank
  • YahooMyWeb

22 Comments so far
Leave a comment

Nice! Maybe you could post this to oss4lib.org?

Thanks, -dc

Hi.. I modified this so that it runs on PHP4. also, your call to gettype never actually validates the numbers.

/* http://www.blyberg.net
* @Desc ISBN Class, adapted from ISBN.pm - http://www.manasystems.co.uk/isbnpm.html
*/
 
function isbn_convert($isbn) {
        $isbn2 = substr("978" . trim($isbn), 0, -1);
        $sum13 = isbn_genchksum13($isbn2);
        $isbn13 = "$isbn2-$sum13";
        return ($isbn13);
    }
 
function isbn_gettype($isbn) {
        $isbn = trim($isbn);
        if (preg_match('%[0-9]{12}?[0-9Xx]%s', $isbn)) {
            if (isbn_validatettn($isbn)==1){
                    return 13;
                       } else {return(-1);}
 
                } else if (preg_match('%[0-9]{9}?[0-9Xx]%s', $isbn)) {
              if (isbn_validateten($isbn)==1){
                    return 10;
                       } else {return -1;}
        } else {
            return -1;
        }
    }
 
function isbn_validateten($isbn) {
        $isbn = trim($isbn);
        $chksum = substr($isbn, -1, 1);
        $isbn = substr($isbn, 0, -1);
        if (preg_match('/X/i', $chksum)) { $chksum="10"; }
        $sum = isbn_genchksum10($isbn);
        if ($chksum == $sum){
            return 1;
        }else{
            return 0;
        }
    }
 
function isbn_validatettn($isbn) {
        $isbn = trim($isbn);
        $chksum = substr($isbn, -1, 1);
        $isbn = substr($isbn, 0, -1);
        if (preg_match('/X/i', $chksum)) { $chksum="10"; }
        $sum = isbn_genchksum13($isbn);
        if ($chksum == $sum){
            return 1;
        }else{
            return 0;
        }
    }
 
function isbn_genchksum13($isbn) {
        $isbn = trim($isbn);
        for ($i = 0; $i

Fixed some buggyness in your checksum routines:

I seemed to get some ISBN 10’s that would calc incorrectly using your code (ex:0756612950)

function isbn_genchksum13($isbn) {
        $t = 2;
        $isbn = trim($isbn);
                $b=0;
                for($i = 1; $i &lt;= 12; $i++){
                   $c = substr($isbn,($i-1),1);
                  if ($i % 2==0){
                   $a = (3 * $c);
                  } else {
                   $a = (1 * $c);
                  }
                   $b=$b+$a;
                }
                $sum = 10 - ($b % 10);
        return $sum;
    }
 
function isbn_genchksum10($isbn) {
        $t = 2;
        $isbn = trim($isbn);
                $b=0;
                for($i = 0; $i &lt; 9; $i++){
                   $c = substr($isbn,$i,1);
                   $a = (($i+1) * $c);
                   $b=$b+$a;
                }
                $sum = ($b % 11);
        return $sum;
    }

Mike,

Thanks for these fixes! I’ll get them packaged up when I have a moment or two… :)

Here’s a couple of additional simple functions to clean out spaces and dashes, and also one to convert from ISBN-13 back into ISBN-10, which is nice for searches etc. I’m using it with PHP4 but you can easily adapt it to PHP5 by changing the “$this->” string.

//Clean out the dashes and spaces from passed ISBN
function cleandashes($isbn){
return $isbn = str_replace(array('-', ' '), '', $isbn);
}

//Conver ISBN-13 back into ISBN-10
function convert13($isbn) {
$isbn2 = substr("" . trim($isbn), 3, 13);
$sum13 = $this->genchksum10($isbn2);
$isbn13 = $isbn2.$sum13;
return ($isbn13);
}

Had an error in my last post, ISBN-13 to ISBN-10 should work now.


//Convert ISBN-13 back into ISBN-10
function convert13($isbn) {
$isbn2 = substr("" . trim($isbn), 3, 9);
$sum10 = genchksum10($isbn2);
$isbn10 = $isbn2.$sum10;
return ($isbn10);
}

One last fix, checksums of 10 need to be converted to “X”. Don’t forget to test for lowercase “x” too.

//Conver ISBN-13 back into ISBN-10
function convert13($isbn) {
$isbn2 = substr(”" . trim($isbn), 3, 9);
$sum10 = $this->genchksum10($isbn2);
if ($sum10==10) {$sum10=’X';}
$isbn10 = $isbn2.$sum10;
return ($isbn10);
}

[...] John Blyberg’s PHP port of the PERL ISBN-10/13 tool [...]

Mikes code almost works, it’s missing one vital part though.
add if($sum == 10) $sum = 0; before the return statement in genchksum13.
Like this:
public function genchksum13($isbn) {
$t = 2;
$isbn = trim($isbn);
$b=0;
for($i = 1; $i

If You need java class to convert from 10 to 13-digit ISBN no use my free source on my WEB page http://www.nofate.info?menu=5
Have a nice day

Hi! Very nice site! Thanks you very much! qfEIKafpsRX

Hi,
thanks for this PHP port and for the useful comments. I wonder if there is a case where the check digit of a ISBN-13 could be ‘x’ or ‘X’. From this page : http://en.wikipedia.org/wiki/ISBN#Check_digit_in_ISBN_13 I think it’s impossible. It can only be a decimal digit from 0 to 9.

So, if I’m right, the isbn_gettype should be :
function isbn_gettype($isbn) {
$isbn = trim($isbn);
if (preg_match(’%[0-9]{13}?%s’, $isbn)) {
if (isbn_validatettn($isbn)==1){
return 13;
} else {return(-1);}

} else if (preg_match(’%[0-9]{9}?[0-9Xx]%s’, $isbn)) {
if (isbn_validateten($isbn)==1){
return 10;
} else {return -1;}
} else {
return -1;
}
}

and the isbn_validatettn function should be :

function isbn_validatettn($isbn) {
$isbn = trim($isbn);
$chksum = substr($isbn, -1, 1);
$isbn = substr($isbn, 0, -1);
$sum = isbn_genchksum13($isbn);
if ($chksum == $sum){
return 1;
}else{
return 0;
}
}

I just realize that the question mark has no sense in :
if (preg_match(’%[0-9]{13}?%s’, $isbn))
so it should be :
if (preg_match(’%[0-9]{13}%s’, $isbn))

One more time, sorry. I think the test should be :
if (preg_match(’%^[0-9]{13}$%s’, $isbn))

Hi,

Thanks for producing this, I found a javascript version, but wanted a PHP version for my site.

This code has saved me a lot of time.

Thanks again!

cannot get this working.
just including it throws:

Parse error: syntax error, unexpected T_STRING, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or ‘}’ in /usr/home/www/htdocs/test/ISBN_script.php on line 11

so I changed public function to function and (not surprisingly)

Fatal error: Undefined class name ’self’ in /usr/home/www/htdocs/test/ISBN_script.php on line 13

This is the collection of ISBN code I’m actively using, compiled from the original code and the comments.

I added the isnb_dashes($isbn) function, which accepts a 10 or 13 digit ISBN number and adds the dashes. This does not check the validity of the string, it just returns it. If it isn’t 10 or 13 characters long, the function returns false.


function isbn_convert($isbn) {
$isbn2 = substr("978" . trim($isbn), 0, -1);
$sum13 = isbn_genchksum13($isbn2);
$isbn13 = "$isbn2-$sum13";
return ($isbn13);
}

function isbn_gettype($isbn) {
$isbn = trim($isbn);
if (preg_match('%[0-9]{12}?[0-9Xx]%s’, $isbn)) {
if (isbn_validatettn($isbn)==1){
return 13;
} else {return(-1);}

} else if (preg_match(’%[0-9]{9}?[0-9Xx]%s’, $isbn)) {
if (isbn_validateten($isbn)==1){
return 10;
} else {return -1;}
} else {
return -1;
}
}

function isbn_validateten($isbn) {
$isbn = trim($isbn);
$chksum = substr($isbn, -1, 1);
$isbn = substr($isbn, 0, -1);
if (preg_match(’/X/i’, $chksum)) { $chksum=”10″; }
$sum = isbn_genchksum10($isbn);
if ($chksum == $sum){
return 1;
}else{
return 0;
}
}

function isbn_validatettn($isbn) {
$isbn = trim($isbn);
$chksum = substr($isbn, -1, 1);
$isbn = substr($isbn, 0, -1);
if (preg_match(’/X/i’, $chksum)) { $chksum=”10″; }
$sum = isbn_genchksum13($isbn);
if ($chksum == $sum){
return 1;
}else{
return 0;
}
}

function isbn_genchksum13($isbn) {
$t = 2;
$isbn = trim($isbn);
$b=0;
for($i = 1; $i genchksum10($isbn2);
if ($sum10==10) {$sum10=’X';}
$isbn10 = $isbn2.$sum10;
return ($isbn10);
}

## ISBN Add Dashes
function isbn_dashes($isbn) {
switch(strlen($isbn)):
case 13:
return
substr($isbn,0,3).”-”
.substr($isbn,3,1).”-”
.substr($isbn,4,3).”-”
.substr($isbn,7,5).”-”
.substr($isbn,12,1);
break;
case 10:
return
substr($isbn,0,1).”-”
.substr($isbn,1,3).”-”
.substr($isbn,4,5).”-”
.substr($isbn,9,1);
break;
default: return false; break;
endswitch;
}

Hi Adam, your function isbn_dashes(); does not place the hyphens on the right place most of the times. It may be correct with some US-ISBN numbers, I doubt you’ve read the official guidelines:

Hyphenation Instructions

Thijs, thanks for the pointer. I’m in the US, dealing with American books. It never occurred to me that there would be a standard for hyphenating or that international books would be hyphenated differently.

I poked around the site and didn’t see a guide for the 13 digit numbers. I assume its the same as 10, except with the dash added after the opening 978.

I will update my function when I have some free time, and I’ll post the code here.

Am I crazy or is none of the code on this page complete?

Lines like this: for($i = 1; $i genchksum10($isbn2);

and blocks of code that end like this:

function isbn_genchksum13($isbn) {
$isbn = trim($isbn);
for ($i = 0; $i

Surely can’t be correct. What is going on here? Is everyone just not good at copy and pasteing? Am I the idiot? I’m baffled.

Here is a txt version

http://tinyurl.com/28ncrk

I have quite a complete ISBN test tool that does all of the above and also does GTIN-14. It’s for php5, but could likely be backported to php4 fairly easily.

If anyone is interested you’ll find it at http://www.phpclasses.org/browse/package/1707.html

It’s just called ISBNcheck (not a clever name, but it works)

kapn



Leave a comment
Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

(required)

(required)