Как получить первый символ строки на PHP?

Подробнее разберёмся с этим казалось бы простым вопросом.

В PHP можно обращаться к строке, как к массиву символов, но те, кто решили сделать это через $str[0] будут правы только в некоторых случаях. Так как вы читаете этот текст на русском языке, использовать такой метод вам строго противопоказано, дальше поймёте почему.

Вариант с substr($str, 0, 1) уже чуть ближе к истине, но у него такая же проблема, как и у первого метода: они оба получат символ из первого байта строки, а значит сработают только если символ влезает в один байт, или проще говоря - этот метод сработает только на английских словах.

Мы же живём в этоху победившего UTF8, в которой один символ может занимать от 1 до 4 байт например:

# ❯ php -a
# Interactive shell

php > echo bin2hex('s')
# 73 // 1 байт

php > echo bin2hex('ъ');
# d1 8a // 2 байта

php > echo bin2hex('€');
# e2 82 ac // 3 байта

php > echo bin2hex('𐍈');
# f0 90 8d 88 // 4 байта

А вот, что мы получим, если попробуем получить первый символ, обращаясь к строке как к массиву:

php > echo 's'[0];
# s // HEX у этого символа всё ещё 73, поэтомы мы получаем нормальную букву s
php > echo 'ъ'[0];
# � // Здесь от 'ъ' остался только первый байт, `d1`, у которого нет соответствующего символа
php > echo '€'[0];
# � // Та же история, осталось только e2
php > echo '𐍈'[0];
# � // Тут взяли только f0

Абсолютно то же самое произойдёт, если использовать substr($str, 0, 1). Если кто-то ещё сомневается, попробуйте выполнить echo substr('ъ', 0, 1) . 'ъ'[1]; и посмотрите, что получится.

Для работы с мультибайтовым кодировками в PHP есть целый набор функций, который начинаются на mb_, в данном случае мы можем воспользоваться функцией mb_substr, чтобы получить первый символ строки:

php > echo mb_substr('s', 0, 1);
# s
php > echo mb_substr('ъ', 0, 1);
# ъ
php > echo mb_substr('€', 0, 1);
# €
php > echo mb_substr('𐍈', 0, 1);
# 𐍈

mb_substr может работать даже с эмоджи, которые могут состоять из нескольких UTF8 символов. Но эмоджи могут быть составными, то есть состоять из нескольких эмоджи (модификаторы цвета кожи, или пола) и с такими эмоджи mb_substr будет возвращать только первую пиктограмму:

php > echo mb_substr('👍😅🤡', 0, 1);
// 👍
php > echo mb_substr('😵‍💫', 0, 1);
// 😵
php > echo mb_substr('😮‍💨', 0, 1);
// 😮

Но это уже совсем другая история.