Skip to content

Instantly share code, notes, and snippets.

@jacobsantos
Last active April 25, 2017 19:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jacobsantos/6b451c993111a4caa14505a90201923a to your computer and use it in GitHub Desktop.
Save jacobsantos/6b451c993111a4caa14505a90201923a to your computer and use it in GitHub Desktop.
Luhn PHP
79927398710 is not valid.
79927398713 is valid.
<?php
/**
* Split number into separate digits.
*
* @param int|string $value
* This value will be broken into separate digits.
*
* Please note that this will be sanitized to the int type. Letters will be zeroed.
* @return array
*/
function split_digits($value) {
return array_map('intval', str_split((string) $value));
}
/**
* Callback for filtering even indexes.
*
* Please note that while this could be called, it is not meant to be used directly.
*
* @param $mixed $value
* This is ignored.
* @param $mixed $key
* This is converted to an integer and checked if it is even.
* @return bool
*/
function filter_even_indexes($value, $key) {
// Unfortunately, we need to increase the index by one to modulo correctly.
// Could use 1 instead of 0, but that would probably be less clear.
return (($key + 1) % 2) === 0;
}
/**
* Callback for filtering odd indexes.
*
* Please note that while this could be called, it is not meant to be used directly.
*
* @see filter_odd_indexes()
* Negates return value.
*
* @param $mixed $value
* This is ignored.
* @param $mixed $key
* This is converted to an integer and checked if it is odd.
* @return bool
*/
function filter_odd_indexes($value, $key) {
return !filter_even_indexes($value, $key);
}
/**
* Split array by indexes.
*
* Technically, this allows for filtering the given array on the callback
* providing both value and key respectively. The scope for this is limited.
*
* @param array $numbers
* List of numbers to split.
* @param callable $callback
* Callback for filtering numbers.
* @return array
*/
function split_indexes(array $numbers, callable $callback) {
return array_filter($numbers, $callback, ARRAY_FILTER_USE_BOTH);
}
/**
* Split list of numbers by odd indexes.
*
* @param array $numbers
* @return array
*/
function split_odd_indexes(array $numbers) {
return split_indexes($numbers, 'filter_odd_indexes');
}
/**
* Split list of numbers by even indexes.
*
* @param array $numbers
* @return array
*/
function split_even_indexes(array $numbers) {
return split_indexes($numbers, 'filter_even_indexes');
}
/**
* Check the number based on luhn algorithm.
*
* @param int|string $value
* Number to check.
* @return bool
* Whether number passes or fails luhn checksum.
*/
function luhn_checksum($value) {
$numbers = array_reverse(split_digits($value));
$total = array_reduce(split_even_indexes($numbers), function($total, $value) {
return $total + array_sum(split_digits($value * 2));
}, array_sum(split_odd_indexes($numbers)));
return ($total % 10) === 0;
}
/**
* Display whether number is valid based on luhn checksum.
*
* @param int|string $value
* Number to check.
* @return void
*/
function is_number_valid($value) {
if (luhn_checksum($value)) {
echo sprintf('%d is valid.', $value);
} else {
echo sprintf('%d is not valid.', $value);
}
}
is_number_valid(79927398710);
is_number_valid(79927398713);
79927398710 is not valid.79927398713 is valid.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment