2016-08-11 16:36:34

Вопрос для любителей ПеХеПе

PHP

PHP Code

Вашему внимаю предлагается жвачка для ума для любителей true-кодинга на PHP.

Этот вопрос хорошо подходит для того, чтобы задавать на собеседовании и замучить кандидата до смерти, тк сразу и без подготовки на него ответят далеко не все, а только те соискатели, кто очень хорошо знает предметную область и глубоко погружен в некоторые тонкости языка.

Итак, задача казалось бы вполне тривиальная и очень типичная:

Получить в переменную $id значение параметра id из GET, при условии, что это цифра и больше 0, в остальных случаях - FALSE.

И это бы было тривиально, если бы не следующие ограничения:

Запись должна быть в одну строку $id = ...; (точку с запятой можно поставить только один раз в конце строки), а операторы 'if' и '?', а также фигурные скобки использовать нельзя. Обращаться к массивам $_* нельзя.

Тест-кейс который должен выполняться:

index.php?id=100500  => 100500
index.php?id=-10     => FALSE
index.php?id=0       => FALSE
index.php?id=        => FALSE
index.php?id=wtf     => FALSE
index.php?           => FALSE

Ну что ж, давайте рассуждать как это сделать.


Если бы не ограничения на if и ?, то все было бы предельно просто и очень прозрачно. Требование написать в одну строку явно намекает на то, что надо использовать какую-то хитрую функцию... или хитро использовать какую-то функцию.

Для этого нам больше всего подходит функция filter_input, и если внимательно изучить мануал от нее, то можно найти все что нужно для решения задачи: нам нужно использовать фильтр FILTER_VALIDATE_INT, благодаря которому мы поймем, что нам передали число, а также установить опции, в которых min_range будет 1. Это отсечет все цифры меньше 1 и все, что является не цифрой.

Задача почти решена, за одним небольшим исключением - если в GET нет нужного нам параметра, то filter_input считает это шибкой фильтрации и отдает NULL в качестве результата. И тут на помощь приходит магия: в конец добавляем or после которого присваиваем FALSE  нашей переменной, и благодаря or этот код сработает только тогда, когда результат от предыдущей операции интерпретируется как ложь. Таким образом, все что не прошло через filter_input станет FALSE, задача решена.

И если вы были достаточно внимательны, то уже увидели правильный ответ в виде кода на изображении в самом начале :)

А еще есть более элегантное решение, просто добавить в опции 'default' => FALSE, и тогда все что не пройдет валидацию превратится в FALSE, что позволит избавится от or и магии :)