Как правильно обрезать строку в php

3

Чтобы разобраться в этом вопросе, нам для начала необходимо понять, что мы подразумеваем под «Правильно обрезать строку».

Я не буду писать здесь SEO текст, поэтому сразу перейду к делу. Когда я искал готовое решение этой проблемы (и не только я один :)), то набрел на простой способ, который режет строку с указанным количеством символов. Вроде удобно, что еще нужно? Но как оказалось, все не так просто и вот почему.

Есть такая функция, при помощи которой мы будем считать кол-во символов в обрезаемом тексте. Называется она strlen(). Она и вправду считает, но только не символы, а байты. Это очень важно. Поскольку, если у нас латиница кодируется в один байт, то с кириллицей сложнее — в 2 байта. И все бы ничего, если бы у нас был текст только латиницей писан.

Но часто, да что там часто — почти всегда(!) в нашем кириллическом тексте встречаются латинские слова: будь-то названия компаний, функций, терминов и много другого. И тогда весь наш подсчет символов строки становится каким-то сумасшествием. Чтобы было понятней, я приведу простой пример:

echo strlen('Ваша функция не работает'); # выведет 45 символов, хотя символов по факту - 24

echo strlen('Your function is not working'); # выведет 28 символов, по факту символов - 28

echo strlen('Ваша функция is not working'); # выведет 38 символов, хотя по факту символов - 27

Поэтому для того, чтобы нам это побороть, я приведу рабочую функцию, которая сначала берет весь текст, кодирует его в windows-1251, считает кол-во символов и, если надо — обрезает строку добавляя троеточие в конце и кодирует обратно в UTF-8. Покажу как это работает на примере:

Эта функция полностью рабочая и, что важно, не оставляет в конце обрезанной строки знаки вопроса или другие не понятные символы. Кстати, они появляются тогда, когда мы режем кириллицу по пополам. То есть кириллическая буква «а» = 2 байта, но если так получается, что скрипт ее режет пополам (ведь он у нас считает не символы, а байты), то у нас остается от «а» всего 1 байт, поэтому и выводятся всякие непонятные символы.

Еще стоит отметить, что пробел, как полноправный символ тоже имеет 1 байт.