Walidacja numeru PESEL w PHP

PESEL, czyli Powszechny Elektroniczny System Ewidencji Ludności. Wszyscy obywatele Polski go posiadają, ale właściwie z czego się składa?
PESEL - założenia poprawnego numeru
- Ma 11 znaków,
- Składa się wyłącznie z cyfr,
- Ma poprawną sumę kontrolną,
- Rok urodzenia jest >= 1800 i < 2300,
- Miesiąc jest >= 1 i <= 12,
- Dzień jest >= 1 i <= liczbie dni w danym miesiącu i danym roku,
1. Sprawdzenie ilości znaków
W pierwszym kroku sprawdzimy jaką długość ma wprowadzony przez użytkownika ciąg znaków. Poprawny PESEL składa się z dokładnie z 11 znaków.
if (strlen($pesel) !== 11) {
// PESEL nie ma 11 znaków
}
2. Sprawdzenie, czy PESEL zawiera wyłącznie cyfry
Sprawdziliśmy, czy PESEL składa się z 11 znaków. Warto jednak dodać, że nie mogą to być dowolne znaki. PESEL składa się wyłącznie z cyfr. Sprawdźmy zatem, czy podany ciąg znaków to tylko cyfry.
if (ctype_digit($pesel) === false) {
// PESEL nie zawiera wyłącznie cyfr
}
3. Sprawdzenie sumy kontrolnej numeru PESEL
W tym kroku sprawdzimy jedną z ważniejszych rzeczy, czyli sumę kontrolną. Mamy wyznaczone wagi do kolejnych w PESELu cyfr. Aby obliczyć sumę kontrolną, musimy kolejne cyfry numeru PESEL pomnożyć przed odpowiednią wagę. Jeżeli otrzymana w ten sposób suma kontrolna podzielona przez 10, nie zwraca reszty, to PESEL jest poprawny.
// Waga kolejnych cyfr do obliczenia sumy kontrolnej
$weights = [1, 3, 7, 9, 1, 3, 7, 9, 1, 3, 1];
// Rozbicie cyfr na elementy tablicy
$digits = str_split($pesel);
$checksum = array_reduce(array_keys($digits), function ($carry, $index) use ($weights, $digits) {
return $carry + $weights[$index] * $digits[$index];
});
if ($checksum % 10 !== 0) {
// PESEL ma błędną sumę kontrolną
}
4. Data urodzenia z numeru PESEL
Przykład PESELu dla osoby urodzonej w latach '90 (92052015150):
- Rok to pierwsze dwie cyfry, czyli 92 to 1992 rok,
- Miesiąc to 3 i 4 cyfra, czyli 05 to 5 miesiąc, czyli maj,
- Dzień to 5 i 6 cyfra, czyli 20. dzień miesiąca,
Przykład PESELu dla osoby urodzonej po 2000 roku (05252073527):
- Rok to pierwsze dwie cyfry, czyli 05 to 2005 rok,
- Miesiąc to 3 i 4 cyfra, czyli 25 - 20 to 5 miesiąc, czyli maj,
- Dzień to 5 i 6 cyfra, czyli 20. dzień miesiąca,
Miesiąc nie zawsze mówi wprost, w którym miesiącu ktoś się urodził, zasada jest następująca:
- +20 dla osób urodzonych w latach 2000-2099,
- +40 dla osób urodzonych w latach 2100-2199,
- +60 dla osób urodzonych w latach 2200-2299,
- +80 dla osób urodzonych w latach 1800-1899,
Musimy wykonać kilka obliczeń matematycznych, aby rozszyfrować pełny rok i miesiąc. Poniżej fragment kodu PHP, który ma skomentowane kolejne obliczenia.
$year = substr($pesel, 0, 2);
$month = substr($pesel, 2, 2);
$day = substr($pesel, 4, 2);
// Pierwsza cyfra z miesiąca, między 0 i 9
$century = substr($pesel, 2, 1);
// Dodajemy 2
// Przykład: 0 -> 2, 9 -> 11
$century += 2;
// Reszta z dzielenia przez 10
// Przykład: 9 -> 9, 10 -> 0, 11 -> 1
$century %= 10;
// Dzielimy na 2 i zaokrąglamy w dół
// Przykład: 2 -> 1, 4 -> 2, 9 -> 4
$century = round($century / 2, 0, PHP_ROUND_HALF_DOWN);
// Dodajemy 18
// Przykład: 1 -> 19, 4 -> 23
$century += 18;
// Pełny rok
// Przykład: 19 i 92, 20 i 05
$year = $century.$year;
// Przekształcenie "miesiąca" z PESEL na prawidłowy format
// Przykład: 25 -> 5 -> 05
$month = str_pad($month % 20, 2, '0', STR_PAD_LEFT);
5. Sprawdzenie daty w numerze PESEL
Mamy odczytany dzień, miesiąc i rok z numeru PESEL. Teraz nadszedł moment, kiedy możemy sprawdzić, czy podane są prawidłowe.
if ($year < 1800 || $year > 2299) {
// Błędny rok
}
if ($month < 1 || $month > 12) {
// Błędny miesiąc
}
if ($day < 1 || $day > cal_days_in_month(CAL_GREGORIAN, $month, $year)) {
// błędny dzień
}
Podsumowanie
W ten sposób sprawdziliśmy, czy podany przez użytkownika PESEL jest prawidłowy i ma poprawną sumę kontrolną. Czy weryfikowaliście już w ten sposób PESEL? Macie jakieś pytania?
Kategorie: PHP + MySQL. Tagi: #php. Źródło obrazków: Pixabay, Font awesome.