Проверка непустоты текста в ПХП

Только не бомбите, я для себя.

В ПХП оператор == проверяет равенство значений безотносительно типа. Поэтому строка «42» и число 42 с его точки зрения равны.

Это удобно: в большинстве случаев не нужно вообще думать о типах, просто сорок два равно сорока двум. Аналогично равны, например и логическая истина и число 1. Когда важно, чтобы значения были не просто равны, но ещё и совпадали по типу, используется оператор строгого равенства === .

Часто важно убедиться, что переменная не пуста. Можно проверить так:

if (@$text) { ... }

Как бы «если текст есть, то». Любая непустая строка приведётся к логически истине, при этом и пустая строка, и null, и даже неопределённая переменная приведутся ко лжи, и условие не выполнится.

Но есть нюанс. Число 0 тоже приводится к логической лжи. С этим был связан баг в Эгее: если текст заметки состоят целиком из нуля, заметку не получалось сохранить, потому что до одной из таких строчек этот текст доходил в виде числа, и условие не выполнялось. А это вполне легальный текст заметки.

У меня рука не поднимется исправить так:

if (@$text or $text === 0) { ... }

Поэтому теперь я проверяю наличие текста так:

if ((string) @$text !== '') { ... }

Не так элегантно, как было, но вроде жить можно. Или нет?

Продолжение

Подписаться на блог
Отправить
Дальше
14 комментариев
Sergei Kolesnikov 2019

@$text? Серьёзно? Если же документация и Stack Overflow.
На этих ресурсах можно узнать, что еспециальная функция empty($text), которая проверяет переменную на пустоту.

Alexander Steeloid 2019

выше комментарий тоже некорректный, т. к. empty($text) при $text = ’0’; тоже вернет что текст пуст

использовать @ — признак очень плохого кода

ну и по идее переменная всегда должна быть определена выше (т. е. как может так случится, что переменная $text может быть не определена? зачем @?)
если $text как и должно быть определена где-то выше наверняка, то правильно так:
if(strlen($text))

если может быть, что $text может быть не определена, то так:
if(isset($text) && strlen($text))

впрочем, (string)$text !== ’’ тоже норм, вполне

а, и ещё: https://monosnap.com/file/pJEH5Tacra7uOAgnDeW7lQYjumWpm4 — от этого у программистов шевелятся волосы :)

Ola 2019
Илья Бирман 2019

Но как? :-)

Vasily Petrov 2019

Так в пхп же уже можно включить типы и не париться. Или я неправильно почитал пару минут стэковерфлоу?

Евгений Степанищев 2019

Vasily, у него не ПХП7, поэтому он не может «включить типы». По той же причине, Alexander, Илье лучше не использовать strlen — до седьмой версии это полноценный вызов функции (а не опкод), а они в ПХП довольно дорогие.

Alexander Steeloid 2019

Евгений, этот вызов происходит один раз при посте, его дороговизна не имеет значения в данном контексте

Евгений Степанищев 2019

Alexander, а зачем делать такой анализ, если сразу можно делать одинаково во всех ситуациях более универсальным способом. Тем более вы ещё и сайдэффект используете — что пустая строка содержит ноль байт, а ноль, так случилось, приводится к false.

Alexander Steeloid 2019

Евгений, согласен с одинаково для всех, но про пустую строку — ведь пустой строки там и надо избежать
Если уж в коде активно используется подавление ошибок через эт, то какая уж разница, жечь так жечь :)
в том случае сойдет и strlen, но в принципе и через сравнение с приведением тоже норм, просто длиннее.
Опять же, мы (ну т. е. я, я знаю что вы тоже используете Эгею, а значит, наверное, можете знать, как там всё устроено) не знаем, как вообще получается переменная $text

4 2019

Оператор @ замедляет выполнение скрипта. Это одна из причин, по которой его использование не рекомендуется (другая — то, что подавлять ошибки в принципе не очень хорошая идея).

Если бы вдруг я столкнулся с такой ситуацией, что переменная может быть не определена и я никак не могу на это повлиять (?), я бы сделал проверку так:

if (isset($text) && $text !== ’’)) {
...
}

Предполагаю, что $text приходит напрямую из $_REQUEST — приводить к строке не обязательно.

Almaziko 2019

Ну как же в комментариях без чайников. Подскажите пожалуйста знающие люди, где обучиться пхп, что бы я потом вот тут смог с вами пхп обсуждать :)

Евгений Степанищев 2019

Например, тут, Almaziko:
https://stc.innopolis.university/

Konstantin Baryshnikov 2019

Про то, что STFU operator — тормозная бяка, уже сказали, но все предлагают использовать isset.

Начиная с php7 есть null coalesce operator, можно писать так:

$text ?? null

С проверкой на непустоту можно как-нибудь так:

if (»» === (string)$a ?? ««)

Если устраивает, что int 0 (но не string «0») будет считаться пустотой, можно короче:

if (»» == $a ?? ««)

Кстати, пройтись по всему коду и сконвертировать по шаблону одно в другое автоматически умеет Rector (https://getrector.org/, также пригодится для перехода с 5 на 7). Конкретно такого правила там нет, но легко дописать.

Илья Бирман 2019

К сожалению, я не могу полагаться на ПХП 7. Я в последнем релизе Эгеи повысил минимальный уровень ПХП с 5.3 до 5.4, и даже это оказалось проблемой для пары пользователей (я не знаю, сколько людей мне не написали и просто решили, что движок не работает).

Konstantin Baryshnikov 2019

Хм. Поддержка PHP 5.6 окончена в январе этого года. А поддержка 5.4 — вообще 4 года назад. Это ж как на windows xp сидеть, минное поле.
Но догадываюсь, что кто-то настроил сервер 10 лет назад и не трогает.

Впрочем, все равно мой комментарий (надеюсь) пригодится, лет через пять :-)

Денис 2019

А зачем вообще нужно публиковать заметку, состоящую целиком из нуля?

Илья Бирман 2019

А зачем вообще публиковать заметку состоящую целиком из буквы „щ“?

Мои книги