Validierung von ISBN
In diesem Tutorial geht es um die Validierung von ISBN.
Vorwort:
Die ISBN (International Standard Book Number) ist eine 10, bzw. seit dem Jahr 2007 eine 13-stellige Zahlenfolge, die ein Buch in eindeutiger Form kennzeichnet.
Die letzte Zahl ist dabei eine Prüfziffer.
Aufgrund der Knappheit von verfügbaren ISBN wurde der Zahlenraum verdoppelt und in das EAN-System überführt.
Näheres dazu und zur Geschichte sowie dem Aufbau einer ISBN kann man in dem entsprechenden
Wikipedia-Artikel nachlesen.
Die Funktionsweise:
Es soll im Verlauf dieses Tutorials ein Funktion erstellt werden, die den boolschen Wert true oder false zurückgibt; in Abhängigkeit davon, ob die übergebene ISBN valid ist - oder nicht.
Die Schnittstelle zum testen der Funktion sieht so aus:
PHP-Code:
<?php
error_reporting(E_ALL);
$ISBN = '3442464552';
echo '<br>'.$ISBN.' -> '.((bISBN($ISBN) === true)?'':'nicht ').'valid';
?>
Diese Zeilen bewirken nur eine Ausgabe mit der Info, ob die angegeben ISBN valid ist, oder nicht.
Doch nun zur eigentlichen Funktion, die die Prüfung vornimmt:
PHP-Code:
<?php
function bISBN($ISBN = false)
{
if($ISBN == 'valid') // hier fehlt noch der passende Teil
{
return true;
}
else
{
return false;
}
}
?>
Das Prinzip soweit sollte klar sein, oder?
die Funktion:
Zuerst müssen alle Striche und Leerzeichen entfernt werden, denn häufig werden diese mit angegeben. Sie enthalten aber keinerlei vewertbaren Informationen.
PHP-Code:
<?php
function bISBN($ISBN = false)
{
// alle leerzeichen entfernen
$ISBN = str_replace(" ", "", $ISBN);
// alle - entfernen
$ISBN = str_replace("-", "", $ISBN);
if($ISBN == 'valid') // hier fehlt noch der passende Teil
{
return true;
}
else
{
return false;
}
}
?>
Der Schritt des Zeichen-entfernens lässt sich auch noch zusammenfassen:
PHP-Code:
<?php
function bISBN($ISBN = false)
{
// störende Zeichen (Punkt und Strich) entfernen
$ISBN = str_replace(array(' ', '-'), '' $ISBN);
if($ISBN == 'valid') // hier fehlt noch der passende Teil
{
return true;
}
else
{
return false;
}
}
?>
Dann muss eine Fallunterscheidung eingebaut werden, denn eine ISBN kann 10stellig, oder (seit Anfang 2007) auch 13stellig sein. Davon hängt aber das verwendete Verfahren zur Berechnung der Prüfziffer ab.
PHP-Code:
<?php
function bISBN($ISBN = false)
{
$ISBN = str_replace(array(' ', '-'), '' $ISBN);
if(strlen($ISBN) == 10)
{
if($ISBN == 'valid') // hier fehlt noch der passende Teil
{
return true;
}
else
{
return false;
}
}
elseif(strlen($ISBN) == 13)
{
if($ISBN == 'valid') // hier fehlt noch der passende Teil
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
?>
Im Gegensatz zur ISBN-10, bei der auch noch ein X als Prüfziffer vorkommen kann (X wie die römische Zahl für 10), ist die ISBN-13 rein numerisch. Das kann daher als weiteres Prüfargument genommen werden!
Des weiteren sind der ISBN-13 3 weitere Zahlen vorgestellt, welche eine Warengruppe deklarieren. Das ist entweder die 978 oder die 979. Auch das kann als weiteres Prüfargument benutzt werden!
PHP-Code:
<?php
function bISBN($ISBN = false)
{
$ISBN = str_replace(array(' ', '-'), '' $ISBN);
if(strlen($ISBN) == 10)
{
if($ISBN == 'valid') // hier fehlt noch der passende Teil
{
return true;
}
else
{
return false;
}
}
elseif(strlen($ISBN) == 13 && is_numeric($ISBN) && (substr($ISBN, 0, 3) == 978 || substr($ISBN, 0, 3) == 979))
{
if($ISBN == 'valid') // hier fehlt noch der passende Teil
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
?>
Die Formel für die Berechnung der Prüfziffer bei ISBN-10 sieht so aus:
Code:
(1*$z1 + 2*$z2 + 3*$z3 + 4*$z4 + 5*$z5 + 6*$z6 + 7*$z7 + 8*$z8 + 9*$z9) modulo 11;
wobei z1 bis z9 die einzelnen Stellen (von links nach rechts) in der ISBN sind.
Wenn die berechnete Zahl mit der letzten Ziffer übereinstimmt, handelt es sich um eine valide ISBN. Hierbei sei noch der Sonderfall erwähnt, dass die Prüfziffer eine 10 sein kann und anstelle dessen dann ein X verwendet wird.
Im PHP-Code sieht das dann so aus:
PHP-Code:
<?php
// als erstes wird die Ziffernfolge in einzelne Zahlen zerlegt:
$z1 = substr($ISBN, 0, 1);
$z2 = substr($ISBN, 1, 1);
$z3 = substr($ISBN, 2, 1);
$z4 = substr($ISBN, 3, 1);
$z5 = substr($ISBN, 4, 1);
$z6 = substr($ISBN, 5, 1);
$z7 = substr($ISBN, 6, 1);
$z8 = substr($ISBN, 7, 1);
$z9 = substr($ISBN, 8, 1);
$z10 = substr($ISBN, 9, 1);
//dann wird der Sonderfall des X berücksichtigt
if(strtoupper($z10) === 'X')
{
$z10 = 10;
}
// nun wird die Prüfziffer berechnet
$pruefziffer = (1*$z1 + 2*$z2 + 3*$z3 + 4*$z4 + 5*$z5 + 6*$z6 + 7*$z7 + 8*$z8 + 9*$z9)%11;
// wenn nun die berechnete Prüfziffer mit der übergebenen Prüfziffer identisch ist, dann handelt es sich um eine valide ISBN
if($z10 == $pruefziffer)
{
return true;
}
else
{
return false; // andernfalls gibt die Prüffunktion ein false zurück
}
?>
Der Überprüfungsschritt am Ende lässt sich auch noch verkürzen (oben nur für das Verständnis lang ausgeschrieben). Die kurze Form sieht so aus:
PHP-Code:
return $z10 === $pruefziffer;
Was passiert hier? Ganz einfach. Wenn die beiden Variablen, als $z13 und $pruefziffer sowohl den gleichen Wert als auch den gleichen Typ haben, dann wird return ein true zurückgeben, andernfalls ein false. Also genau das, was das if-else-Konstrukt auch tut.
Ähnlich geschieht die Überprüfung nun auch bei der ISBN-13, wobei der Sonderfall mit dem X wegfällt und darüber hinaus die Berechnungsformel ein wenig anders aussieht.
PHP-Code:
<?php
// als erstes wird die Ziffernfolge in einzelne Zahlen zerlegt:
$z1 = substr($ISBN, 0, 1);
$z2 = substr($ISBN, 1, 1);
$z3 = substr($ISBN, 2, 1);
$z4 = substr($ISBN, 3, 1);
$z5 = substr($ISBN, 4, 1);
$z6 = substr($ISBN, 5, 1);
$z7 = substr($ISBN, 6, 1);
$z8 = substr($ISBN, 7, 1);
$z9 = substr($ISBN, 8, 1);
$z10 = substr($ISBN, 9, 1);
$z11 = substr($ISBN, 10, 1);
$z12 = substr($ISBN, 11, 1);
$z13 = substr($ISBN, 12, 1);
// nun wird die Prüfziffer berechnet
$pruefziffer = (10-(($z1+$z3+$z5+$z7+$z9+$z11+3*(+$z2+$z4+$z6+$z8+$z10+$z12))%10))%10;
// wenn nun die berechnete Prüfziffer mit der übergebenen Prüfziffer identisch ist, dann handelt es sich um eine valide ISBN
return $z13 === $pruefziffer;
?>
Wenn nun beides in die Funktion eingebaut wird, sieht diese wie folgt aus:
PHP-Code:
<?php
function bISBN($ISBN = false)
{
$ISBN = str_replace(array(' ', '-'), '' $ISBN);
// Laenge prüfen
if(strlen($ISBN) == 10)
{
// als erstes wird die Ziffernfolge in einzelne Zahlen zerlegt:
$z1 = substr($ISBN, 0, 1);
$z2 = substr($ISBN, 1, 1);
$z3 = substr($ISBN, 2, 1);
$z4 = substr($ISBN, 3, 1);
$z5 = substr($ISBN, 4, 1);
$z6 = substr($ISBN, 5, 1);
$z7 = substr($ISBN, 6, 1);
$z8 = substr($ISBN, 7, 1);
$z9 = substr($ISBN, 8, 1);
$z10 = substr($ISBN, 9, 1);
//dann wird der Sonderfall des X berücksichtigt
if(strtoupper($z10) === 'X')
{
$z10 = 10;
}
// nun wird die Prüfziffer berechnet
$pruefziffer = (1*$z1 + 2*$z2 + 3*$z3 + 4*$z4 + 5*$z5 + 6*$z6 + 7*$z7 + 8*$z8 + 9*$z9)%11;
// wenn nun die berechnete Prüfziffer mit der übergebenen Prüfziffer identisch ist, dann handelt es sich um eine valide ISBN
return $z10 === $pruefziffer;
}
elseif(strlen($ISBN) == 13 && is_numeric($ISBN) && (substr($ISBN, 0, 3) == 978 || substr($ISBN, 0, 3) == 979))
{
// als erstes wird die Ziffernfolge in einzelne Zahlen zerlegt:
$z1 = substr($ISBN, 0, 1);
$z2 = substr($ISBN, 1, 1);
$z3 = substr($ISBN, 2, 1);
$z4 = substr($ISBN, 3, 1);
$z5 = substr($ISBN, 4, 1);
$z6 = substr($ISBN, 5, 1);
$z7 = substr($ISBN, 6, 1);
$z8 = substr($ISBN, 7, 1);
$z9 = substr($ISBN, 8, 1);
$z10 = substr($ISBN, 9, 1);
$z11 = substr($ISBN, 10, 1);
$z12 = substr($ISBN, 11, 1);
$z13 = substr($ISBN, 12, 1);
// nun wird die Prüfziffer berechnet
$pruefziffer = (10-(($z1+$z3+$z5+$z7+$z9+$z11+3*(+$z2+$z4+$z6+$z8+$z10+$z12))%10))%10;
// wenn nun die berechnete Prüfziffer mit der übergebenen Prüfziffer identisch ist, dann handelt es sich um eine valide ISBN
return $z13 === $pruefziffer;
}
else
{
return false;
}
}
?>
Nun noch ein paar ISBN um die Funktionalität zu testen
PHP-Code:
<?php
error_reporting(E_ALL);
$ISBN = '3442464552';
echo '<br>'.$ISBN.' -> '.((bISBN($ISBN) === true)?'':'nicht ').'valid';
$ISBN = '3442464555';
echo '<br>'.$ISBN.' -> '.((bISBN($ISBN) === true)?'':'nicht ').'valid';
$ISBN = '3-442-46455-2';
echo '<br>'.$ISBN.' -> '.((bISBN($ISBN) === true)?'':'nicht ').'valid';
$ISBN = '978-3-7657-2780-1';
echo '<br>'.$ISBN.' -> '.((bISBN($ISBN) === true)?'':'nicht ').'valid';
$ISBN = '9783765727801';
echo '<br>'.$ISBN.' -> '.((bISBN($ISBN) === true)?'':'nicht ').'valid';
$ISBN = '9793765727801';
echo '<br>'.$ISBN.' -> '.((bISBN($ISBN) === true)?'':'nicht ').'valid';
$ISBN = '9793765727800';
echo '<br>'.$ISBN.' -> '.((bISBN($ISBN) === true)?'':'nicht ').'valid';
?>
Wer nun eine ISBN-10 in eine ISBN-13 umwandeln möchte, hat hier alles an Wissen dazu zusammengetragen.
Einfach eine 978 davorstellen und die alte Prüfziffer durch eine neue ersetzen. Fertig.
Solltet Ihr Fragen zu dem Tutorial haben, so schreibt bitte einen Beitrag im
PHP-Forum mit einem Verweis auf dieses Tutorial.
Danke.
Ich hoffe, dass ich Euch hier etwas weiterhelfen konnte.
Grüße Jann Hendrik
Nachtrag:
Trotz sorgfältiger Prüfung schleichen sich immer kleinere Fehler ein. Darüber hinaus gibt es auch Programmabschnitte, die man verbessern kann. Ein thread, in welchem derartige Vorschläge zu diesem Tutorial gesammelt werden ist
hier verlinkt.
edit:
Ich habe einige der Kritikpunkte verbessert. Andere werden noch geprüft und dann ggf. noch eingearbeitet.