ISBNコードの確認・変換用PHP関数

June 1, 2011 – 4:15 pm

いまさらという感じもしないわけでもないが、ISBNの新旧コード変換(13桁<->10桁)そしてチェックを行うPHP関数を作ったのでメモしておいた。
あわせて、この関数の仕様を明確にするため、サンプルコードを与えておいた。

書籍コードISBNについて、「書籍コードとアマゾンAPIによる検索」に(解説)記事を書いたことがある。アマゾンなどの書籍データを活用しようとすると、ISBNの変換とかチェック機能を持つ関数を作っておくと便利と思い、PHP関数を作った。

作成した関数の機能は以下のとおり:

  • isbn10_To_Isbn13(): 10桁のISBNコードを引数とし、これを13桁に変換し関数値として返す。
  • isbn_To_Isbn10(): 13桁もしくは10桁のISBNコードを引数とし、10桁のISBNコードを関数値として返す。(アマゾンのASINコードとして使用することを意識)
  • chkdigit13(): 引数が13桁ISBNコードとして(桁数ならびにチェックディジットからみて)適正かどうか確認。
  • chkdigit10(): 引数が10桁ISBNコードとして(桁数ならびにチェックディジットからみて)適正かどうか確認。

サンプル計算: 上記の4種の関数を組み合わせて作成したサンプル出力用コードと出力例;

サンプル出力用PHPコード(test_isbn.php):


<?php
require_once('./isbn_converter.php' );

isbn_checker('412004193X');
isbn_checker('4120041936');
isbn_checker('978-4-306-07289-3');
isbn_checker('9784861721212');
isbn_checker('4-06-23497-2');

function isbn_checker($id_for_check) {

  echo "\nChecked ID: " . $id_for_check . "\n";

  $chkd13 = chkdigit13($id_for_check);
  if (     $chkd13===0 ) echo $id_for_check . " is correct ISBN-13.\n";
  else if ($chkd13===-1) echo $id_for_check . " has 13 digits but not correct checkdigit.\n";
  if (     $chkd13===0 ) {
       $isbn10 = isbn_To_Isbn10( $id_for_check );
       echo "ISBN10 of ISBN13(" . $id_for_check . ") is " . $isbn10 . ".\n";
  }
  else if ( $chkd13===-2 ) {
       $chkd10 = chkdigit10($id_for_check);
       if( $chkd10 === 0 ) {
           echo $id_for_check . " is correct ISBN-10.\n";
           $isbn13 = isbn10_To_Isbn13( $id_for_check );
           echo "ISBN13 of ISBN10(" . $id_for_check . ") is " . $isbn13 . ".\n";
       }
       else if ($chkd10===-1) echo $id_for_check . " has 10 digits but not correct checkdigit.\n";
       else echo $id_for_check . " is neither ISBN10 nor ISBN13.\n";
  }
}
?>

出力例:

$ php test_isbn.php

Checked ID: 412004193X
412004193X is correct ISBN-10.
ISBN13 of ISBN10(412004193X) is 9784120041938.

Checked ID: 4120041936
4120041936 has 10 digits but not correct checkdigit.

Checked ID: 978-4-306-07289-3
978-4-306-07289-3 is correct ISBN-13.
ISBN10 of ISBN13(978-4-306-07289-3) is 4306072894.

Checked ID: 9784861721212
9784861721212 is correct ISBN-13.
ISBN10 of ISBN13(9784861721212) is 4861721210.

Checked ID: 4-06-23497-2
4-06-23497-2 is neither ISBN10 nor ISBN13.

作成した関数
isbn_converter.php;


<?php
//*****************************************************************
//*   isbn10_To_Isbn13( $isbn10 )
//*----------------------------------------------------------------
//*      
//*      Argument:   $isbn10
//*      Return  :   $isbn13
//*                 
//*****************************************************************
function isbn10_To_Isbn13( $isbn10 ) {

   $char     = str_split($isbn10);
   $char_out = array();
   $j = 0;
   for ( $i=0; $i<sizeof($char); $i++ ) {
       if ( is_numeric($char[$i]) || $char[$i] === 'x' || $char[$i] === 'X' )  {
          $char_out[$j] = $char[$i];
          $j = $j + 1;
       }
   }

   $sum = 0;
   for ( $j=0; $j<9; $j=$j+2 ) $sum = $sum + (int)$char_out[$j]; 
   $sum = 3*($sum+7)  + 17;
   for ( $j=1; $j<9; $j=$j+2 ) $sum = $sum + (int)$char_out[$j]; 
   $amari = $sum % 10;
   $digit = 10 - $amari; 
    
   $isbn13 = "978";
   for ($i=0; $i<9; $i++) $isbn13 = $isbn13 . $char_out[$i];
   if ($digit ===10) $digit=0;
   $isbn13 = $isbn13 . (string)$digit;

   return $isbn13;
}
//*****************************************************************
//*   isbn_To_Isbn10 ( $isbn )
//*----------------------------------------------------------------
//*
//*      Argument:   $isbn 
//*                   (ISBN10(ASIN) or ISBN13)
//*      Return  :   $isbn10
//*                   (ASIN or ISBN10)
//*
//*****************************************************************
  function isbn_To_Isbn10 ( $isbn )  {
    $char     = str_split($isbn );
    // 10 letters assumed correct ASIN
    if ( sizeof($char) === 10 )  return $isbn;
    //
    $char_out = array();
    $j = 0;
    for ( $i=0; $i<sizeof($char); $i++ ) {
      if ( is_numeric($char[$i]) ) {
           $char_out[$j] = $char[$i];
           $j = $j + 1;
      }
    }

    if( $j === 10 ) for($i=0; $i<10; $i++) $char_isbn[$i]=$char_out[$i]; 
    else {
      $j   = 0;
      $sum = 0;
      for ( $i=3; $i<12; $i++ ) {
        $char_isbn[$j] = $char_out[$i];
        $sum = (10 - $j) * (int)$char_isbn[$j] + $sum;
        $j = $j + 1;
      }
      $amari = $sum % 11;
      $digit = 11 - $amari;
      if ( $digit == 10 )     $char_isbn[$j] = 'X';
      else if( $digit == 11 ) $char_isbn[$j] = '0';
      else               $char_isbn[$j] = (string)$digit;
    }

    $isbn10 = $char_isbn[0];
    for ( $i=1; $i<10; $i++ ) $isbn10 = $isbn10 . $char_isbn[$i];

    return $isbn10;
 }
//*****************************************************************
//*   chkdigit13 ( $isbn13 )
//*----------------------------------------------------------------
//*   Check ISBN-13:
//*      Argument:   $isbn13
//*      Return  :   0 : correct
//*                 -2 : Not 13 digits
//                  -1 : Check digit is not correct
//*
//*****************************************************************
function chkdigit13( $isbn13 ) {
    $char     = str_split($isbn13);

    $char_out = array();
    $j = 0;
    for ( $i=0; $i<sizeof($char); $i++ ) {
      if ( is_numeric($char[$i]) ) {
           $char_out[$j] = $char[$i];
           $j = $j + 1;
      }
    }
    if( $j != 13 ) {
         /* echo "Error: Not 13 digits \n"; */
         return -2;
    }

    $sum = 0;
    for ( $j=1; $j<12; $j=$j+2 ) $sum = $sum + (int)$char_out[$j];
    $sum = 3*$sum;
    for ( $j=0; $j<12; $j=$j+2 ) $sum = $sum + (int)$char_out[$j];
    $amari = $sum % 10;
    $digit = 10 - $amari;
    if($digit === 10 ) $digit = 0;
    if ( $char_out[12] === (string)$digit ) return 0;
    else {
       /* echo "Error: Check digit Not Correct!  0001 \n"; */
       return -1;
    }
}
//*****************************************************************
//*   chkdigit10 ( $isbn10 )
//*----------------------------------------------------------------
//*
//*   Check ISBN-10:
//*
//*      Argument:   $isbn10
//*      Return  :   0 : Correct 
//*                 -2 : Error:  Not 10 digits
//*                 -1 :         Check digit is not correct
//*                           
//*****************************************************************
function chkdigit10( $isbn10 ) {
   $char     = str_split($isbn10);
   $char_out = array();
   $j = 0;
   for ( $i=0; $i<sizeof($char); $i++ ) {
       if ( is_numeric($char[$i]) || $char[$i]==='x'  || $char[$i]==='X')  {
          if( $char[$i] ==='X' ) $char[$i]='x';
          $char_out[$j] = $char[$i];
          $j = $j + 1;
       }
   }

   if ( $j !== 10 ) {
          /* echo "ERROR: Not 10 digits! \n";  */
             return -2;
   }
   $j   = 0;
   $sum = 0;
   for ( $i=0; $i<9; $i++ ) $sum=(10-$i)*(int)$char_out[$i]+$sum;
   $amari = $sum % 11;
   $digit = (string)(11-$amari);
   if ( $digit == '10' && $char_out[9] ==='x' || $digit=='11' && $char_out[9] === '0' 
     || $digit === $char_out[9] ) return 0; 
   else{
      /* echo "ERROR: CheckDigit Not Correct!\n"; */
      return -1;
   }  
}
?>


  1. 2 Responses to “ISBNコードの確認・変換用PHP関数”

  2. isbn_converter.php で、

    “`
    if ( $digit == ’10’ && $char_out[9] ===’x’ || $digit==’11’ && $char_0ut[9] === ‘0’
    “`
    は、
    “`
    if ( $digit == ’10’ && $char_out[9] ===’x’ || $digit==’11’ && $char_out[9] === ‘0’
    “`
    の間違いではないでしょうか?

    By developer on Sep 7, 2018

  3. ご指摘のとおりです。

    本文を修正をしておきました。
    ありがとうございました。

    なお、このバグによってISBN-10でcheck-digitが0のときエラーになってしまい。ISBNの値が正しくないとの判定をされてしまいます。例えば、4000612530をチェックしようとすると、

    Checked ID: 4000612530
    PHP Notice:  Undefined variable: char_0ut in /home/yukichi/work/isbn_converter.php on line 153
    4000612530 has 10 digits but not correct checkdigit.
    

    となります。

    By yama on Sep 8, 2018

Post a Comment