Если в любом аргументе ничего не передать и нажать на "Посчитать": Выведется сообщение: "Введите число!". Но логично было бы: "Аргументы 1 или 2 не переданы". Хотя мы ничего не передавали, но на самом деле мы передали пустую строку, а функция filter_input() обработала ее и вернула false. Тем самым выражение:
if ($x1 === null || $x2 === null) {
return 'Аргументы 1 или 2 не переданы';
}
не сработает =*(
но можно сделать так:
<?php
if (empty($_GET)) {
return 'Ничего не передано';
}
if (empty($_GET['operation'])) {
return 'Операция не передана';
}
if ($_GET['x1'] === "" || $_GET['x2'] === "") {
return 'Аргументы 1 или 2 не переданы';
}
$x1 = filter_input(INPUT_GET, 'x1', FILTER_VALIDATE_FLOAT);
$x2 = filter_input(INPUT_GET, 'x2', FILTER_VALIDATE_FLOAT);
if ($x1 === NULL || $x2 === null) {
return 'Аргументы 1 или 2 не переданы';
}
if ($x1 === false || $x2 === false) {
return 'Введите число!';
}
$operations = $_GET['operation'];
switch ($operations) {
case '+':
$result = $x1 + $x2;
break;
case '-':
$result = $x1 - $x2;
break;
case '/':
$result = $x2 !== 0 ? ($x1 / $x2) : 'На ноль делить нельзя';
break;
case '*':
$result = $x1 * $x2;
break;
default:
return 'Операция не поддерживается';
}
$expression = $x1 . ' ' . $operations . ' ' . $x2 . ' = ';
return $expression . $result;
Хотя я уверен что есть способ поделикатнее, но это не точно =)
А в чем ошибка, если отправить пустую строку, то есть ничего не писать просто нажать на кнопку посчитать, выведет Аргументы 1 или 2 не преданы. Все верно же.
То есть в данном случае мы просто проверяем - не передано ли в полях что-либо, но не проверяем есть ли сами поля, верно?
В таком случае, если да, то, возможно, следует взять на вооружение и всегда использовать
либо empty, либо сравнение с null или isset, верно?
Тема проверки дается не очень, возвращаюсь к ней. Как-то не совсем усвоил - зачем нужно проверять. Как могут навредить моему сайту, если нет проверки.
Для чего удалять переменную из адресной строки, чтобы получить ошибку - вот не понимаю.
Вы в статье пишите, что если в консоли разработчика удалить поле, то форма будет косячная. Почему? После обновления страницы все работает.
Вот если бы понять важность этой проверки на конкретном примере...
По поводу д.з. к этой статье.
Принял переменные из глобального массива Гет через фильтр FILTER_VALIDATE_FLOAT.
Больше возможностей для использования фильтров в коде не нашел.
$x1 = filter_input(INPUT_GET, 'x1', FILTER_VALIDATE_FLOAT);
$x2 = filter_input(INPUT_GET, 'x2', FILTER_VALIDATE_FLOAT);
if ($x1 === null || $x2 === null) {
return 'Аргументы 1 или 2 не переданы';
}
В таком случае, если да, то, возможно, следует взять на вооружение и всегда использовать
либо empty, либо сравнение с null или isset, верно?
Совершенно верно
Как-то не совсем усвоил - зачем нужно проверять.
Потому что любая ошибка - это потенциальная уязвимость. К примеру, вывод ошибки с путём до файла - это уязвимость, которая так и называется - раскрытие пути. Сам по себе путь не является чем-то опасным, но может помочь злоумышленнику лучше понять структуру проекта, узнать версию движка, или что-то ещё, что может упростить эксплуатацию других уязвимостей.
Ваше приложение не должно содержать ошибок. Вот прям совсем.
Получилось так. Немного не допер, как сделать аналогичный, но кастомный фильтр для $_GET['operation'], через FILTER_CALLBACK. Как-то там сильно наворочено. Или это еще рано?
if (empty($_GET)) {
return 'Ничего не передано';
}
2) Если массив не пуст, теперь проверяем есть ли заданные переменные в массиве:
if ($x1 === null || $x2 === null || $operation === null) {
return 'Ничего не передано';
}
3) Если есть все переменные, проверяем есть ли во всех переменных аргументы:
if ($x1 === false && $x2 === false && empty($operation)) {
return 'Ничего не передано';
}
*Хотя согласен, этот пункт можно опустить
Просто все эти 3 пункта могут быть выполнены, только если вмешиваться в работу программы, через строку, поэтому и описал все случаи одним комментарием, так сказать для "взламывателей" )))
Пользователь же, который будет "честно" работать через форму, фактически будет работать только вот с этими условиями:
Какое значение будет в x1, если не удастся распарсить число?
Ну если верить описанию filter_input, то при удачной фильтрации возвращается само число, при неудачной фильтрации, возвращается false, а при отсутствии самой переменной, возвращается null. А если использовать флаг FILTER_NULL_ON_FAILURE, то наоборот. Во всяком случае, я так понял.
Просто все эти 3 пункта могут быть выполнены, только если вмешиваться в работу программы, через строку, поэтому и описал все случаи одним комментарием, так сказать для "взламывателей" )))
всё правильно
Пользователь же, который будет "честно" работать через форму, фактически будет работать только вот с этими условиями:
ни в коем случае не полагайтесь на это
я просто у вас спросил, для чего, не просил ничего переписывать)
нужна только на случай, если удалить все аргументы единовременно. А если по отдельности, то будут работать другие проверки. Во всяком случае, вроде бы все возможное протестил, ошибок не нашел.
и удалить все аргументы в строке "result.php?x1=&operation=&x2="
То выйдет ошибка Результат вычислений:
Введите число
Что согласитесь, не логично, ведь у нас нет еще и оператора. Но такой случай может быть только если вмешиваться в саму работу через строку, как я уже писал выше. Ведь через страницу формы мы можем опустить ввод чисел, но обязательно должны ввести, как минимум оператор (+ стоит по умолчанию). Поэтому я и сделал дополнительную проверку именно на этот случай. Но это как бы в идеале, самое главное программа не крашится, а что именно написано в ошибке, уже не столь важно. Это я перфекционист, просто )))
Добрый день! Спасибо.
Освоил урок не без помощи комментариев. Пока возился, возник вопрос немного не в тему. Я добавил в калькуляторе, в файлах index.php и calc.php, две операции % и **. Всё работает. Но при вводе операции отображение вот такое.
Комментарий забыла исправить.
Использую флаг null_on_failure, непонятно зачем, его убрала.
//фильтруем значения, полученные методом GET
$x1 = filter_input(INPUT_GET, 'x1', FILTER_VALIDATE_FLOAT);
$x2 = filter_input(INPUT_GET, 'x2', FILTER_VALIDATE_FLOAT);
//проверяем, что переменные определены в массиве GET
if ($x1 === null || $x2 === null) {
return 'Аргументы 1 или 2 отсутствуют';
}
//проверяем, что переданное значение прошло фильтрацию
if ($x1 === false || $x2 === false) {
return 'Переданные аргументы 1 или 2 не являются числами!';
}
<?php
if (empty($_GET)) {
return 'Ничего не передано';
}
if (empty($_GET['operation'])) {
return 'Операция не передана';
}
if (!isset($_GET['x1'], $_GET['x2'], $_GET['operation'])) {
return 'Аргументы не переданы';
}
$x1 = filter_input(INPUT_GET, 'x1', FILTER_VALIDATE_FLOAT);
$x2 = filter_input(INPUT_GET, 'x2', FILTER_VALIDATE_FLOAT);
if ($x1 === null || $x2 === null) {
return 'Аргументы 1 или 2 не переданы';
}
if ($x1 === false || $x2 === false) {
return 'Введите число';
}
$operations = $_GET['operation'];
switch ($operations) {
case '+':
$result = $x1 + $x2;
break;
case '-':
$result = $x1 - $x2;
break;
case '/':
$result = $x2 !== 0 ? ($x1 / $x2) : 'На ноль делить нельзя';
break;
case '*':
$result = $x1 * $x2;
break;
default:
return 'Операция не поддерживается';
}
$expression = $x1 . ' ' . $operations . ' ' . $x2 . ' = ';
return $expression . $result;
Добрый день. У меня получился такой код, но он не совсем корректно работает. А именно: если задать пустое поле, то оно распознается как false, а не как null. И в результате выдается сообщение: "Введите число".
$x1 = $_GET['x1'] ?? null;
$x2 = $_GET['x2'] ?? null;
if ($x1 === null || $x2 === null) {
return 'Аргументы 1 или 2 не переданы';
}
Здравствуйте! Можете объяснить логику сего действа?
Фактически, это проверка на отсутствие полей вообще. Но в случае проверки x1/x2 на пустую строку(на что как бы намекает текст ошибки - что аргумент 1 или 2 не передан) это работать не будет, т.к. для строгого равенства пустая строка не null. Тут спасает проверка функцией is_numeric, которая выдаст ошибку(введите число) в случае пустой строки и без которой строгое сравнение работать не будет. Но корректно ли это? Это же вроде разные проверки - на пустоту и на число/не число. Вообще не совсем понятно, зачем тут строгое сравнение, как и во многих других случаях по курсу, где можно обойтись без него.
Насколько я понимаю, можно было бы просто в приведенном выше коде использовать нестрогое сравнение:
$x1 = $_GET['x1'] ?? null;
$x2 = $_GET['x2'] ?? null;
if ($x1 == null || $x2 == null) {
return 'Аргументы 1 или 2 не переданы';
}
Строгое сравнение должно быть по умолчанию. Смысл писать == null и подразумевать под этим проверку на пустую строку? Это делает код непонятным и непредсказуемым. Хотите проверить на пустую строку - напишите === ''. Пустой массив === [].
Тогда нужно делать явную проверку на пустую строку, используя строгое равенство(=== ''), иначе проверка в Вашем коде выше работает не корректно. Я так думаю...))
Извините, что не по теме. Подскажите, как сделать, чтобы PHPStorm выводил функцию var_damp как у Вас, построчно, а не одной строкой (плохо читабельно). Google мои вопросы не совсем понимает. Будет круто, если найдется ссылка с дополнительными лайфхаками по настройкам. Спасибо!
Добрый вечер!
Существует ли возможность функцией filter_input() обработать регулярное выражение, например "[+-/*//]" для контроля ввода операций калькулятора, в доках функции что-то не увидел про регулярки. И есть ли смысл это делать в данном коде, ведь операции обрабатываются switch'ем.
<?php
// Обработчик калькулятора для домашнего задания
if (empty($_GET)) {
return 'Ничего не передано';
}
if (empty($_GET['operation'])) {
return 'Операция не передана';
}
$x1 = $_GET['x1'] ?? null;
$x2 = $_GET['x2'] ?? null;
if (($x1 === null) && ($x2 === null)) {
return 'Аргументы не переданы';
}
if ($x1 === null) {
return 'Аргумент 1 не передан';
}
if ($x2 === null) {
return 'Аргумент 2 не передан';
}
$operations = $_GET['operation'] ?? null;
$x1 = filter_input(INPUT_GET, 'x1', FILTER_VALIDATE_FLOAT);
$x2 = filter_input(INPUT_GET, 'x2', FILTER_VALIDATE_FLOAT);
if (($x1 === false) && ($x2 === false)) {
return 'Аргументы не переданы или они "не-число"';
}
if ($x1 === false) {
return 'Аргумент 1 не передан или он "не-число"';
}
if ($x2 === false) {
return 'Аргумент 2 не передан или он "не-число"';
}
switch ($operations) {
case '+':
$result = $x1 + $x2;
break;
case '-':
$result = $x1 - $x2;
break;
case '/':
$result = $x2 !== 0.0 ? ($x1 / $x2) : 'На ноль делить нельзя';
break;
case '*':
$result = $x1 * $x2;
break;
default:
return 'Операция не поддерживается или она не передана';
}
$expression = $x1 . ' ' . $operations . ' ' . $x2 . ' = ';
return $expression . $result;
Я вот так сделал
единственное теперь при неправильном вводе не будет сообщений, а аргумент будет принимать значение 0.0
Как-то не очень хорошо ознакомились с функцией. У неё ещё 2 аргумента есть.
Такие решения не принимаются. Должен быть полностью рабочий код.
Исправил:
или необходимо разделить сообщения?
Можно разделить, будет дополнительнвм плюсом. Но в целом, это именно то, что я хотел увидеть)
Спасибо.
Если в любом аргументе ничего не передать и нажать на "Посчитать": Выведется сообщение: "Введите число!". Но логично было бы: "Аргументы 1 или 2 не переданы". Хотя мы ничего не передавали, но на самом деле мы передали пустую строку, а функция filter_input() обработала ее и вернула false. Тем самым выражение:
не сработает =*(
но можно сделать так:
Хотя я уверен что есть способ поделикатнее, но это не точно =)
Бум! И снова ошибка!
А в чем ошибка, если отправить пустую строку, то есть ничего не писать просто нажать на кнопку посчитать, выведет Аргументы 1 или 2 не преданы. Все верно же.
Упс, видимо вам я еще не скидывал) Пройдите дополнительный урок Обработка форм в PHP и исправьте ошибки
Отлично!
Если я правильно понял, то это читается так, что если $_GET['x2'] равно null, то ее значение будет null.
Зачем задавать null если значение и так null?
Потому что без применения этого оператора будет ошибка уровня NOTICE, если этого ключа в массиве не будет.
То есть в данном случае мы просто проверяем - не передано ли в полях что-либо, но не проверяем есть ли сами поля, верно?
В таком случае, если да, то, возможно, следует взять на вооружение и всегда использовать
либо empty, либо сравнение с null или isset, верно?
Тема проверки дается не очень, возвращаюсь к ней. Как-то не совсем усвоил - зачем нужно проверять. Как могут навредить моему сайту, если нет проверки.
Для чего удалять переменную из адресной строки, чтобы получить ошибку - вот не понимаю.
Вы в статье пишите, что если в консоли разработчика удалить поле, то форма будет косячная. Почему? После обновления страницы все работает.
Вот если бы понять важность этой проверки на конкретном примере...
По поводу д.з. к этой статье.
Принял переменные из глобального массива Гет через фильтр FILTER_VALIDATE_FLOAT.
Больше возможностей для использования фильтров в коде не нашел.
Норм!
Не пройдет проверку на пустую строку, т.к. пустая строка это не null
Совершенно верно
Потому что любая ошибка - это потенциальная уязвимость. К примеру, вывод ошибки с путём до файла - это уязвимость, которая так и называется - раскрытие пути. Сам по себе путь не является чем-то опасным, но может помочь злоумышленнику лучше понять структуру проекта, узнать версию движка, или что-то ещё, что может упростить эксплуатацию других уязвимостей.
Ваше приложение не должно содержать ошибок. Вот прям совсем.
Спасибо за ответ!
Получилось так. Немного не допер, как сделать аналогичный, но кастомный фильтр для $_GET['operation'], через FILTER_CALLBACK. Как-то там сильно наворочено. Или это еще рано?
Зачем столько проверок? Какое значение будет в x1, если не удастся распарсить число?
Ну как бы логика была такая.
1) Проверяем сам массив на наличие данных:
2) Если массив не пуст, теперь проверяем есть ли заданные переменные в массиве:
3) Если есть все переменные, проверяем есть ли во всех переменных аргументы:
*Хотя согласен, этот пункт можно опустить
Просто все эти 3 пункта могут быть выполнены, только если вмешиваться в работу программы, через строку, поэтому и описал все случаи одним комментарием, так сказать для "взламывателей" )))
Пользователь же, который будет "честно" работать через форму, фактически будет работать только вот с этими условиями:
Ну если верить описанию filter_input, то при удачной фильтрации возвращается само число, при неудачной фильтрации, возвращается false, а при отсутствии самой переменной, возвращается null. А если использовать флаг FILTER_NULL_ON_FAILURE, то наоборот. Во всяком случае, я так понял.
всё правильно
ни в коем случае не полагайтесь на это
я просто у вас спросил, для чего, не просил ничего переписывать)
а если только одно передано, а второе false? Тогда проверка не сработает. Нужно с помощью ИЛИ проверять, а не И.
Почему не сработает? Тогда сработает эта проверка, так как здесь, как раз все описано с помощью ИЛИ
А эта проверка,
нужна только на случай, если удалить все аргументы единовременно. А если по отдельности, то будут работать другие проверки. Во всяком случае, вроде бы все возможное протестил, ошибок не нашел.
Спасибо. Принято!
Дело в том, что в этой проверке
вот это:
тоже будет проверено. И проверка с && не имеет смысла
Не соглашусь. Эта проверка
проверяет только наличие переменных, а не аргументов в этих переменных (судя по описанию фильтра):
Т.е. если удалить эту проверку
и удалить все аргументы в строке "result.php?x1=&operation=&x2="
То выйдет ошибка
Результат вычислений:
Введите число
Что согласитесь, не логично, ведь у нас нет еще и оператора. Но такой случай может быть только если вмешиваться в саму работу через строку, как я уже писал выше. Ведь через страницу формы мы можем опустить ввод чисел, но обязательно должны ввести, как минимум оператор (+ стоит по умолчанию). Поэтому я и сделал дополнительную проверку именно на этот случай. Но это как бы в идеале, самое главное программа не крашится, а что именно написано в ошибке, уже не столь важно. Это я перфекционист, просто )))
Добрый день! Спасибо.
Освоил урок не без помощи комментариев. Пока возился, возник вопрос немного не в тему. Я добавил в калькуляторе, в файлах index.php и calc.php, две операции % и **. Всё работает. Но при вводе операции отображение вот такое.
Подскажите, что с этим можно сделать.
Ну так у тебя там слеш и написан)
Да уж! Спасибо.
??
А, отвечай на комментарий, а не создавай новую ветку, а то не понял к чему ты это написал)
ok
Не нужно после FILTER_VALIDATE_FLOAT
Ошибки нужно возвращать просто строкой, а не записывать их в переменную $result. Там только результат успешной операции.
Спасибо, исправила!
Ошибка в $result всё равно записывается
Исправила
Теперь ноль прибавить нельзя
Снова поправила!
Теперь ок)
Спасибо, большое!
Не очень понимаю, правильный ли кусок кода я заменила на filter_input?
Нужно выбрать что-то одно.
Ошибку не нужно записывать в результат. Сразу возвращайте её, как и ошибки выше
исправила)
Для чего в двух местах получаете значение?
Убрала.
Нет здесь никаких ключей)
А почему сравниваете с false, а потом с null? В каких случаях будут эти значения?
Комментарий забыла исправить.
Использую флаг null_on_failure, непонятно зачем, его убрала.
Отлично!
Добрый день. У меня получился такой код, но он не совсем корректно работает. А именно: если задать пустое поле, то оно распознается как false, а не как null. И в результате выдается сообщение: "Введите число".
Для этого можно расширить одно из условий, проверив что на входе не пустая строка
Добрый день.
На ноль нельзя. Но ноль на другие числа можно.
Исправил
Супер!
что скажешь? как бы усовершенствовал чтоб убрать возможные повторения кода?
filter_input вместо раздельной обработки POST-запроса и filter_var
Здравствуйте! Можете объяснить логику сего действа?
Фактически, это проверка на отсутствие полей вообще. Но в случае проверки x1/x2 на пустую строку(на что как бы намекает текст ошибки - что аргумент 1 или 2 не передан) это работать не будет, т.к. для строгого равенства пустая строка не null. Тут спасает проверка функцией is_numeric, которая выдаст ошибку(введите число) в случае пустой строки и без которой строгое сравнение работать не будет. Но корректно ли это? Это же вроде разные проверки - на пустоту и на число/не число. Вообще не совсем понятно, зачем тут строгое сравнение, как и во многих других случаях по курсу, где можно обойтись без него.
Насколько я понимаю, можно было бы просто в приведенном выше коде использовать нестрогое сравнение:
Строгое сравнение должно быть по умолчанию. Смысл писать == null и подразумевать под этим проверку на пустую строку? Это делает код непонятным и непредсказуемым. Хотите проверить на пустую строку - напишите === ''. Пустой массив === [].
Тогда нужно делать явную проверку на пустую строку, используя строгое равенство(=== ''), иначе проверка в Вашем коде выше работает не корректно. Я так думаю...))
При отсутствии исходных данных в калькуляторе не возвращает это сообщение. Все остальное работает.
php-8
Так может данные все же есть? Пустые строки - тоже данные. Что выводит var_dump($_GET)?
Начал следующий урок и понял в чем тут дело.
Извините, что не по теме. Подскажите, как сделать, чтобы PHPStorm выводил функцию var_damp как у Вас, построчно, а не одной строкой (плохо читабельно). Google мои вопросы не совсем понимает. Будет круто, если найдется ссылка с дополнительными лайфхаками по настройкам. Спасибо!
https://php.zone/post/krasivyy-vyvod-var-dump-openserver
Добрый вечер!
Существует ли возможность функцией filter_input() обработать регулярное выражение, например "[+-/*//]" для контроля ввода операций калькулятора, в доках функции что-то не увидел про регулярки. И есть ли смысл это делать в данном коде, ведь операции обрабатываются switch'ем.
Кажется здесь проще простым сравнением обойтись.
не нужно на один и тот же параметр 2 проверки делать
Для случая отсутствия аргументов лучше сделать проверку на то что их нет. Дальше основной код писать не в фигурных скобках.
В случае деления на ноль нужно делать return по аналогии с остальными ошибками
Здравствуйте, есть что дополнить?