PHPでISBNコードをASINコードに変換する

(1/1)
ASIN は、Amazon.comが独自に決めた商品番号だ。
今回は、PHPを使って、国際標準図書番号「ISBN」から、ASIN へコード変換するプログラムを作ってみることにする。

(2023年9月30日)pahooInputData導入

サンプル・プログラムの実行例

PHPでISBNコードをASINコードに変換する

目次

サンプル・プログラム

圧縮ファイルの内容
isbn2asin.phpサンプル・プログラム本体。
pahooInputData.phpデータ入力に関わる関数群。
使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。
isbn2asin.php 更新履歴
バージョン 更新日 内容
1.5.0 2023/10/01 pahooInputData導入
1.4 2021/05/03 PHP8対応,リファラチェック追加
1.3 2016/06/04 ハイフン無視,Amazon商品リンク
1.2 2015/09/20 bug-fix
1.1 2010/05/18 bug-fix
pahooInputData.php 更新履歴
バージョン 更新日 内容
1.4.1 2023/09/30 コメントの訂正
1.4.0 2023/09/09 $_GET, $_POST参照をfilter_input()関数に置換
1.3.0 2023/07/11 roundFloat() 追加
1.2.0 2023/04/22 exitIfLessVersion() 追加
1.1.2 2023/02/05 validString() 修正

ISBNコード

ISBN(International Standard Book Number)は国際標準図書番号とも呼ばれ、書籍を特定するための世界共通の番号体系である。
2006年(平成18年)12月31日までは10進数10桁の番号が用いられていたが、2007年(平成19年)以降には10進数13桁の番号へ移行した。ここでは現行規格を中心に説明する。

ISBNコードは10進数13桁からなり、その内容は下記の通りである。
内容
13-11識別番号(978または979)
10グループ記号(出版国などを表す数字で、日本は4)
9-6出版者記号
5-2書名記号
1チェックデジット
たとえば、「楽しいPHP入門」(クジラ飛行机/インプレスジャパン/2009年(平成21年)11月)という書籍のISBNコードは 9784844327882 である。これを分解すると下記のようになる。
内容
識別番号978
グループ記号4
出版者記号8443
書名記号2788
チェックデジット2
出版者番号 8443 はインプレスコミュニケーションズに与えられた番号である。

チェックデジットはモジュラス10 ウェイト3 という方式である。以下のように計算する。
  1. チェックデジットをのぞく一番左側の桁から順に1,3,1,3を掛けて、それらの和を取る。
  2. 和を10で割った余りを10から引く。ただし10で割って出た余りの下1桁が0の場合は0とする。
これを上記の書籍に適用すると、
9×1+7×3+8×1+4×3+8×1+4×3+4×1+3×3+2×1+7×3+8×1+8×3=138
138%10=8
10-8=2
となり、チェックデジットの 2 を得ることができる。

ちなみに、旧規格(2007年12月31日まで)は10進数10桁であるが、グループ記号、出版者記号、書名記号は現行規格と同じである。チェックデジットの計算方法は異なる(モジュラス11 ウェイト10-2)。

ASINコード

ASIN(Amazon Standard Identification Number)は、Amazon.comが独自に決めた商品番号のことで、書籍についてはISBNの旧規格と同じ番号であった。

ISBNの現行規格についても、識別番号が978であるものについては、桁数10-2は同一である。ただしチェックデジットの計算方法がモジュラス11 ウェイト10-2であるため、最後の1桁の数字が異なる。

モジュラス11 ウェイト10-2方式は、以下のように計算する。
  1. チェックデジットを除いた左側の桁から10,9,8‥‥2を掛けてそれらの和を取る。
  2. 和を11で割って出た余りを11から引く。
前述の「楽しいPHP入門」のASINコードは 4844327887 である。このチェックデジットを求めようとすると、
4×10+8×9+4×8+4×7+3×6+2×5+7×4+8×3+8×2=268
268%11=4
11-4=7
となり、チェックデジットの 7 を得ることができる。

ISBNとASINの関係

9 7 8 ISBNコード 4 8 4 4 3 2 7 8 8 2 4 8 4 4 3 2 7 8 8 7 ASINコード 13 10 5 2 1

解説:ISBNコードをASINコードに変換する

 151: /**
 152:  * ISBNコードをASINコードに変換する
 153:  * @param   string $isbn ISBNコード(10進数10桁 or 13桁)
 154:  * @return  string ASINコード(10進数10桁)/FALSE:変換に失敗
 155: */
 156: function isbn2asin($isbn) {
 157:     //旧ISBNコードの場合はそのまま返す
 158:     if (preg_match('/^[0-9]{9}[0-9X]$/', $isbn) == 1) {
 159:         if (cd11($isbn!substr($isbn, 9, 1))     return FALSE;
 160:         return $isbn;
 161:     }
 162: 
 163:     //入力値チェック
 164:     if (preg_match('/^[0-9]{13}$/', $isbn!1)    return FALSE;
 165:     if (cd10($isbn!substr($isbn, 12, 1))        return FALSE;
 166:     if (preg_match('/^978/', $isbn) == 0)           return FALSE;
 167: 
 168:     $code = substr($isbn, 3, 10);       //10-1桁目を取り出す
 169:     $cd = cd11($code);
 170: 
 171:     return substr($isbn, 3, 9. $cd;
 172: }

 118: /**
 119:  * チェックデジットの計算(モジュラス11 ウェイト10-2)ASIN用
 120:  * @param   string $code 計算するコード(最下位桁がチェックデジット)
 121:  * @return  int チェックデジット
 122: */
 123: function cd11($code) {
 124:     $cd = 0;
 125:     for ($pos = 10$pos >2$pos--) {
 126:         $n = substr($code, (10 - $pos), 1);
 127:         $cd +$n * $pos;
 128:     }
 129:     $cd = $cd % 11;
 130:     $cd = 11 - $cd;
 131:     if ($cd == 10)  $cd = 'X';
 132:     if ($cd == 11)  $cd = '0';
 133:     return $cd;
 134: }

 136: /**
 137:  * チェックデジットの計算(モジュラス10 ウェイト3)
 138:  * @param   string $code 計算するコード(最下位桁がチェックデジット)
 139:  * @return  int チェックデジット
 140: */
 141: function cd10($code) {
 142:     $cd = 0;
 143:     for ($pos = 13$pos >2$pos--) {
 144:         $n = substr($code, (13 - $pos), 1);
 145:         $cd +$n * (($pos % 2) == 0 ? 3 : 1);
 146:     }
 147:     $cd = $cd % 10;
 148:     return ($cd == 0? 0 : 10 - $cd;
 149: }

変換処理自体は、前述のISBNおよびASINの定義にしたがって計算しているだけである。
ただ、入力値のチェックは細かく行っている。

入力値が10進数10桁なら旧ISBNとして処理をする。この際、チェックデジットが合っているかどうか検査する。※10桁の末尾が 'X' の時に正常に動作しませんでした。クロメルさん、ご指摘及び改良方法の提案をありがとうございました(2015年9月20日)。

入力値が10進数13桁なら現行ISBNとして処理をする。この際、チェックデジットがあっているかどうか検査する。また、上位3桁が978以外の場合は変換処理ができないようにしてある。

チェックデジットの計算には、ユーザー関数 cd10, cd11 を用意した。

解説:メインプログラム

 238: // メイン・プログラム ======================================================
 239: //パラメータを取得する.
 240: $res = $errmsg = '';
 241: $isbn = getValidString('isbn', $errmsg, DEF_ISBN, 10, 20, TRUE, array('/^[0-9\-]+$/iu'));
 242: 
 243: //ISBN→ASIN変換
 244: if ($errmsg === '') {
 245:     $isbn2 = preg_replace('/\-/', '', $isbn);       //ハイフンを除く
 246:     if (($asin = isbn2asin($isbn2)) === FALSE) {
 247:         $errmsg = "'{$isbn2}' は ISBN コードではありません.";
 248:     } else {
 249:         $res =<<< EOT
 250: ASINコード {$asin}<br>
 251: Amazon商品 <a href="https://www.amazon.co.jp/dp/{$asin}">https://www.amazon.co.jp/dp/{$asin}</a>
 252: 
 253: EOT;
 254:     }
 255: }
 256: 
 257: //表示テキストを作成する.
 258: $HtmlBody = makeCommonBody($isbn, $res, $errmsg);
 259: 
 260: //画面に表示する.
 261: echo $HtmlHeader;
 262: echo $HtmlBody;
 263: echo $HtmlFooter;
 264: 
 265: /*

 373: /**
 374:  * HTML FORMで指定したINPUTの内容を文字列として取り出す(バリデーション付き)
 375:  * filter_input()関数および $argv を参照する.
 376:  * @param   string $key       パラメータ名(省略不可)
 377:  * @param   string $errmsg    エラーメッセージを格納する(省略不可)
 378:  * @param   mixed  $def       初期値(省略時:空文字)
 379:  * @param   int    $minlen    入力可能な最小長(省略時=1)
 380:  * @param   int    $maxlen    入力可能な最大長(省略時=99)
 381:  * @param   bool   $exclusion $patternsはTRUE:受容/FALSE:排除(省略時=TRUE)
 382:  * @param   array  $patterns  受容/排除するパターンマッチ配列(省略時=NULL)
 383:  * @return  string 入力値
 384: */
 385: function getValidString($key, &$errmsg, $def='', $minlen=1, $maxlen=99, $exclusion=TRUE, $patterns=NULL) {
 386:     $data = (string)getParam($key, TRUE, $def);     //URLパラメータを取り出す
 387:     $str = trim($data);                             //先頭・末尾の空白文字を除く
 388:     $str = htmlspecialchars($str);                  //XSS対策
 389:     //文字列バリデーション
 390:     if ($str !'') {
 391:         $res = validString($data, $errmsg, $minlen, $maxlen, $exclusion, $patterns);
 392:     }
 393: 
 394:     return $str;
 395: }

メインプログラムでは、ユーザー関数 getValidString を使って、ISBN コードの長さに合わなかったり、数字とハイフン以外の文字が混じっていたら変換処理をしないようバリデーションチェックを書けている。

また、このプログラムはコマンドラインから単独で利用できるようにしてある。
isbn2asin.php?isbn=9784844327882
のように実行すると、標準出力にASINコードのみが出力される。エラー発生時には 'ERROR' と出力する。

参考サイト

(この項おわり)
header