views:

93

answers:

2

Hi, Does anyone know any VIN number validation code written in PHP? I just need to check if the entered vin number is correct or not?

+2  A: 

It's "VIN." "VIN Number" = "Vehicle Identification Number Number," which doesn't make sense.

You can see a definition of the structure of VINs here:
http://en.wikipedia.org/wiki/Vehicle_identification_number

And you can work from there, or you can grab this script here:
http://www.geekpedia.com/code29_Check-if-VIN-number-is-valid.html


Here is an improved version of the function posted by jordan:

$vin = "1M8GDM9AXKP042788";

function validate_vin($vin) {

    $vin = strtolower($vin);
    if (!preg_match('/^[^\Wioq]{17}$/', $vin)) { 
        return false; 
    }

    $weights = array(8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2);

    $transliterations = array(
        "a" => 1, "b" => 2, "c" => 3, "d" => 4,
        "e" => 5, "f" => 6, "g" => 7, "h" => 8,
        "j" => 1, "k" => 2, "l" => 3, "m" => 4,
        "n" => 5, "p" => 7, "r" => 9, "s" => 2,
        "t" => 3, "u" => 4, "v" => 5, "w" => 6,
        "x" => 7, "y" => 8, "z" => 9
    );

    $sum = 0;

    for($i = 0 ; $i < strlen($vin) ; $i++ ) { // loop through characters of VIN
        // add transliterations * weight of their positions to get the sum
        if(!is_numeric($vin{$i})) {
            $sum += $transliterations[$vin{$i}] * $weights[$i];
        } else {
            $sum += $vin{$i} * $weights[$i];
        }
    }

    // find checkdigit by taking the mod of the sum

    $checkdigit = $sum % 11;

    if($checkdigit == 10) { // checkdigit of 10 is represented by "X"
        $checkdigit = "x";
    }

    return ($checkdigit == $vin{8});
}
Confluence
Apologies, I meant Vehicle Identification number.
boosis
Nissan has provided us with a vin number (JN1GANR35U0100001) which fails this validation. Is there a different calculation for US or EUROPE cars?
boosis
+7  A: 

Here's something I wrote up real quick using the example in the wikipedia article.

Not guaranteed perfect or bug free or super efficient, but should provide you with a solid starting point:

Note: I included the edits provided by Confluence below, making the procedure slightly more succinct.

function validate_vin($vin) {

    $vin = strtolower($vin);
    if (!preg_match('/^[^\Wioq]{17}$/', $vin)) { 
        return false; 
    }

    $weights = array(8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2);

    $transliterations = array(
        "a" => 1, "b" => 2, "c" => 3, "d" => 4,
        "e" => 5, "f" => 6, "g" => 7, "h" => 8,
        "j" => 1, "k" => 2, "l" => 3, "m" => 4,
        "n" => 5, "p" => 7, "r" => 9, "s" => 2,
        "t" => 3, "u" => 4, "v" => 5, "w" => 6,
        "x" => 7, "y" => 8, "z" => 9
    );

    $sum = 0;

    for($i = 0 ; $i < strlen($vin) ; $i++ ) { // loop through characters of VIN
        // add transliterations * weight of their positions to get the sum
        if(!is_numeric($vin{$i})) {
            $sum += $transliterations[$vin{$i}] * $weights[$i];
        } else {
            $sum += $vin{$i} * $weights[$i];
        }
    }

    // find checkdigit by taking the mod of the sum

    $checkdigit = $sum % 11;

    if($checkdigit == 10) { // checkdigit of 10 is represented by "X"
        $checkdigit = "x";
    }

    return ($checkdigit == $vin{8});
}

Note: there is a small percent error with verifying VINs because of the nature of the checksum:

...a match does not prove the VIN is correct, because there is still a 1 in 11 chance of any two distinct VINs having a matching check digit.

Also note: 11111111111111111 will validate against the procedure above. Whether or not you want to check for that is up to you:

Straight-ones (seventeen consecutive '1's) will suffice the check-digit. This is because a value of one, multiplied against 89 (sum of weights), is still 89. And 89 % 11 is 1, the check digit. This is an easy way to test a VIN-check algorithm.

reference: http://en.wikipedia.org/wiki/Vehicle_identification_number#Check_digit_calculation

jordanstephens
respect for going as far as to whip something up to this extent. +5 if I could.
Kris.Mitchell
I have a Discrete Math/Algorithms exam in about 30 minutes, figured it wouldn't hurt to get my mind rolling. : )
jordanstephens
How did the test go?
Confluence
@Confluence the exam was far simpler than I had anticipated: mostly just analyzing time complexity of various algorithms... and thanks for the edit! Programming before noon has never been my strong suit...
jordanstephens