In case someone gets to the question wondering how to use modulus or ‘getting the rest of a division’ (%
):
echo 5 % 3; // outputs 2
(You can take a look at a step-by-step output after this first part)
This is the commented function:
function func_name($docnum){
// make sure there is just numbers in $docnum
$docnum = preg_replace("/[^0-9]/","",$docnum);
// change order of values to use in foreach
$vals = array_reverse(str_split($docnum));
// multiply every other value by 2
$mult = true;
foreach($vals as $k => $v){
$vals[$k] = $mult ? $v*2: $v;
$vals[$k] = (string)($vals[$k]);
$mult = !$mult;
}
// checks for two digits (>9)
$mp = array_map(function($v){
return ($v > 9) ? $v[0] + $v[1] : $v;
}, $vals);
// adds the values
$sum = array_sum($mp);
//gets the mod
$md = $sum % 10;
// checks how much for 10
$result = 10 - $md;
// returns the value
return $result;
}
Some test runs:
$docnum = 5843;
echo func_name($docnum);
Output:
8
$docnum = 1111;
echo func_name($docnum);
Output:
4
$docnum = '-5a84fadsafds.fdar3';
echo func_name($docnum);
Output:
8
$docnum = 4321;
echo func_name($docnum);
Output:
6
This codes outputs the steps…
$docnum = '-5a84fadsafds.fdar3';
echo 'Original Value: ';
print_r($docnum);
echo '<hr>';
$docnum = preg_replace("/[^0-9]/","",$docnum);
echo 'Numbers only: ';
print_r($docnum);
echo '<hr>';
$vals = array_reverse(str_split($docnum));
echo 'Reversed Value: ';
print_r($vals);
echo '<hr>';
$mult = true;
foreach($vals as $k => $v){
$vals[$k] = $mult ? $v*2: $v;
$vals[$k] = (string)($vals[$k]);
$mult = !$mult;
}
echo 'After mult.: ';
print_r($vals);
echo '<hr>';
$mp = array_map(function($v){
return ($v > 9) ? $v[0] + $v[1] : $v;
}, $vals);
echo 'Checked for >9: ';
print_r($mp);
echo '<hr>';
$sum = array_sum($mp);
echo 'All values together: ';
print_r($sum);
echo '<hr>';
$md = $sum % 10;
echo 'Mod: ';
print_r($md);
echo '<hr>';
$result = 10 - $md;
echo 'Final result: ';
print_r($result);
echo '<hr>';
Output:
Original Value: -5a84fadsafds.fdar3
Numbers only: 5843
Reversed Value: Array ( [0] => 3 [1] => 4 [2] => 8 [3] => 5 )
After mult.: Array ( [0] => 6 [1] => 4 [2] => 16 [3] => 5 )
Checked for >9: Array ( [0] => 6 [1] => 4 [2] => 7 [3] => 5 )
All values together: 22
Mod: 2
Final result: 8
Read more about things used in the code:
- http://php.net/manual/en/function.array-reverse.php
- http://php.net/manual/en/function.array-map.php
- http://php.net/manual/en/function.array-sum.php
- http://php.net/manual/en/control-structures.foreach.php
- http://php.net/manual/en/language.operators.arithmetic.php (modulus)
- http://php.net/manual/en/language.types.type-juggling.php (
(string)
)
As suggested by @Floris, you can replace the double-digit sum part with modulus 9, so instead of
$mp = array_map(function($v){
return ($v > 9) ? $v[0] + $v[1] : $v;
}, $vals);
you would have
$mp = array_map(function($v){
return $v % 9;
}, $vals);
and still keep the same output…
6
solved PHP Calculation – Modulus 10 check digit generation [closed]