Match letters beyond a to z in regex
Problem. [a-zA-Z] means the 52 letters of the English alphabet and nothing else. A name check built on it rejects Zoë, José, Łukasz and Анна, and it fails quietly: the form just tells those people their own name is invalid.
The same blind spot hides in strtolower(), which only changes A to Z and leaves É exactly as it is.
Fix. Match Unicode properties instead. \p{L} is any letter in any script, and \p{M} covers combining marks, such as an accent stored as a separate character. Add the u modifier so PCRE reads the pattern and the text as UTF-8 characters rather than single bytes.
// Before: only English letters countfunction isValidName(string $name): bool{ return preg_match("/^[a-zA-Z' \-]+$/", $name) === 1;}isValidName('Zoë Müller'); // falseisValidName('Анна'); // false// After: letters from any language, plus combining accentsfunction isValidName(string $name): bool{ return preg_match("/^[\p{L}\p{M}' \-]+$/u", $name) === 1;}isValidName('Zoë Müller'); // trueisValidName('Анна'); // trueResult. Real names pass and the check still rejects digits and symbols. Laravel's alpha validation rule already works this way, accepting \p{L} and \p{M}, and alpha:ascii is how you opt back into a to z. With the u modifier, preg_match() returns false for text that is not valid UTF-8, which is why the comparison is === 1. When text can hold more than English letters, swap strtolower() and ucfirst() for mb_strtolower() and mb_ucfirst().