Этот урок набрал набрал достаточно большое количество
комментариев и дальнейшее его комментирование отключено.
Если вы хотели убедиться в правильности выполнения ДЗ или у вас возник вопрос по уроку,
посмотрите ранее добавленные комментарии, кликнув по кнопке ниже. Скорее всего вы найдете там то, что искали.
Если это не помогло - задайте вопрос в чате в телеграме - https://t.me/php_zone
Представьте, что в форме пропадает поле x1 и при её отправке вообще прропадает query-параметр x1=что-то
Тогда при выполнении, там где происходит обращение к $_GET['x1'], возникнет ошибка.
Чтобы этого избежать, стоит воспользоваться функцией array_key_exists() или isset() - так вы сможете убедиться, что такой ключ в массиве существует. А если нет - напишете соответствующую ошибку.
Переменная $operations на деле содержит только одну операцию, значит - $operation
При обработке ошибок мы не выводим исходное выражение - если операция не поддерживается, то сразу об этом пишем, без склейки с $expression. Для однообразия при делении на ноль стоит делать также - добавить if и вызывать в нём сразу return, если x2 === 0.
Пока так и не получилось прибавить 0. Пишу позже, может кому поможет. Разобрался, почему не получалось, потому-что проверял x1 и x2 на empty(), и если вводил 0, то php считал, что поле пустое
По поводу 'Нельзя вводить строковые значения' - не совсем правда. В коде проверка только на то, что это не число. Это ещё не значит, что там строка. Правильнее будет сказать именно о том, что значения должны быть числовыми.
Ты случаем не пропустил закрывающий тек </label> для id="operation"?
Проверка на пустоту $_GET и сопутствующее ему выполнение бессмысленны,т.к. селектор по умолчанию предлагает первый вариант и при нажатии кнопки посчитать, это значение передастся.
Для чего задавать label если мы оставляем их пустыми?
Нужно ли в логике в конструкции switch задавать default, если у нас селектор содержит только два варианта?
Проверка на пустоту не бессмысленна - нельзя доверять тому, что придёт от клиента. Нет гарантии что пользователи будут отправлять данные на бекенд исключительно из "правильной" формы. Ничто не мешает им создать свою форму с плохими данными и завалить ваш бекенд ошибками.
В switch лучше всегда добавляйте секцию default - в ней можно обрабатывать внештатные ситуации, когда пришли данные, которых быть не должно.
Если с формы сейчас убрать input x1 или x2, то скрипт посыпется с warning-ами, из-за того что в массиве $_GET вообще нет ключей x1 и x2. Попробуйте исправить.
if (($_GET['x1' === '']) || ($_GET['x2'] === '')) {
Вот здесь будет ошибка, если аргументы в форме вообще отсутствовали. Нужно проверять с помощью isset, затем проверить с помощью is_numeric, привести переменные к float, и только после этого сравнивать с 0 (не строкой, а числом).
if (!is_numeric($x1)) {
return 'Input interger number';
}
is_numeric не гарантирует, что число будет именно целым, текст ошибки некорректен.
<?php
// Проверяем переданны ли данные вобще
if (empty($_POST)) {
return 'Ничего не передано';
}
// проверяем передана ли операция
if (empty($_POST['operation'])) {
return 'операция не передана';
}
/* проверяем переданы ли аргументы, и проверяем числа это или нет.
проверяем можно ли передавать ноль */
if (($_POST['x1'] === '') || ($_POST['x2'] === '')) {
return 'Не переданы аргументы';
}
if (is_numeric($_POST['x1']) || is_numeric($_POST['x2'])) {
} else {
return 'Введите числовое значение';
}
/* создаем переменные в которых будут лежать наши
значения */
$x1 = $_POST['x1'];
$x2 = $_POST['x2'];
$output = $x1 . '' . $_POST['operation'] . '' . $x2 . '=';
switch ($_POST['operation']){
case '+':
$result = $x1 + $x2;
break;
case '-' :
$result = $x1 - $x2;
break;
case '*':
$result = $x1 * $x2;
break;
/* проверяем деление на ноль*/
case '/':
if ($x1 != 0) {
return ' на ноль делить нельзя';
}
$result = $x1 / $x2;
break;
default:
return 'операция не поддерживаеться';
}
return $output . $result;
Если я передам два числа, отличные от нуля, то программа не будет работать. Вы хоть проверяйте, чтобы она хотя бы просто работала, прежде чем отправлять =)
Но этот скрипт должен корректно работать, независимо от формы - нельзя доверять тому, что форма будет корректной. Поэтому нужно проверять сначала, пришли ли эти значения вообще или нет. Для этого можно использовать функцию isset().
Попробуйте в качестве одного из аргументов передать 0. Какой получился результат? Почему так? Дополните код так, чтобы можно было передавать 0.
if (empty(isset($_GET['x1'])) || empty(isset($_GET['x2']))) {
return 'Не переданы аргументы';
}
Усовершенствуйте калькулятор так, чтобы он умножал и делил.
case '*':
$result = $x1 * $x2;
break;
case '/':
if($x2 != 0)
$result = $x1 / $x2 ;
else
return 'Простите, хорошие интерпритаторы на ноль не делят, а я очень хороший! =)';
break;
Что произойдёт, если поделить на ноль? Добавьте обработку такой ситуации.
case '/':
if($x2 != 0)
$result = $x1 / $x2 ;
else
return 'Простите, хорошие интерпритаторы на ноль не делят, а я очень хороший! =)';
break;
Что произойдёт, если в качестве аргумента передать вместо числа строку? Сделайте так, чтобы в качестве аргументов можно было отправить только числа.
if (!is_numeric(trim($_GET['x1'])) || !is_numeric(trim($_GET['x2']))) {
return 'В параметры передана строка, а должно быть число, исправьте и повторите ввод снова!';
}
Какие ещё недостатки есть у этого кода? Как можно нарушить его работу? Что можно улучшить?
От себя добавил чтобы при проверки на строку, очищал пробелы, так как интерпретатор сам приводит к числовым значениям даже если есть пробелы слева и справа
Весь код
<?php
if (empty($_GET)) {
return 'Ничего не передано!';
}
if (empty($_GET['operation'])) {
return 'Не передана операция';
}
if (empty(isset($_GET['x1'])) || empty(isset($_GET['x2']))) {
return 'Не переданы аргументы';
}
if (!is_numeric(trim($_GET['x1'])) || !is_numeric(trim($_GET['x2']))) {
return 'В параметры передана строка, а должно быть число, исправьте и повторите ввод снова!';
}
$x1 = $_GET['x1'];
$x2 = $_GET['x2'];
$expression = $x1 . ' ' . $_GET['operation'] . ' ' . $x2 . ' = ';
switch ($_GET['operation']) {
case '+':
$result = $x1 + $x2;
break;
case '-':
$result = $x1 - $x2;
break;
case '*':
$result = $x1 * $x2;
break;
case '/':
if($x2 != 0)
$result = $x1 / $x2 ;
else
return 'Простите, хорошие интерпритаторы на ноль не делят, а я очень хороший! =)';
break;
default:
return 'Операция не поддерживается';
}
return $expression . $result;
Его использовал, чтобы интерпретатор обрабатывал как 0. А он определял, то ли как null, то ли еще как то. Оттолкнулся от того, что isset() проверяет на существование переменной и после этого нули уже отрабатываются, исходя из этих соображений использовал.
<?php
$x1 = $_GET['x1'];
$x2 = $_GET['x2'];
if ($x1 === '' || $x2 === '') { //1.Дополните код так, чтобы можно было передавать 0.
return 'Не переданы аргументы';
}else if ($x2 == '0' && $_GET['operation'] == '/') { //3.Что произойдёт, если поделить на ноль? Добавьте обработку такой ситуации.
return 'На 0 делить нельзя';
}else if (!is_numeric($x1) || !is_numeric($x2)) { //4. Сделайте так, чтобы в качестве аргументов можно было отправить только числа.
return "Введите числа";
}
$expression = $x1 . ' ' . $_GET['operation'] . ' ' . $x2 . ' = ';
switch ($_GET['operation']) {
case '+':
$result = $x1 + $x2;
break;
case '-':
$result = $x1 - $x2;
break;
case '/': //2.Усовершенствуйте калькулятор так, чтобы он умножал и делил.
$result = $x1 / $x2;
break;
case '*': //2.Усовершенствуйте калькулятор так, чтобы он умножал и делил.
$result = $x1 * $x2;
break;
default:
return 'Операция не поддерживается';
}
return $expression . $result;
Привет. Четвертый пункт задания требует сделать проверку на то, что x1 и x2 являются числами. Если это сделать, то не будет надобности в htmlspecialchars - просто числа не могут быть кодом.
Пятое задание читай так - как можно текущий код поломать (передав что-либо в форму, изменив форму)? Как это можно исправить?
Привет! У меня вопрос по этому "Сделайте так, чтобы в качестве аргументов можно было отправить только числа." Я при создании своей формы установил четкий формат ввода, т.е. если пользователь накосячил в каких-то данных, окно все равно подсвечивается красным. В данном случае, при создании калькулятора, есть смысл устанавливать дополнительные ограничения на получаемые значения параметров из формы или достаточно того, что в форме они и так есть?
Проверку на то, что аргументы переданы стоит делать с помощью isset($_GET['arg']). Потому что если с формы эти поля не будут переданы (если их совсем убрать с формы), то при сравнении $_GET['arg'] === '' возникнет ошибка.
Проверку на то, что аргументы переданы стоит делать с помощью isset($_GET['arg']). Потому что если с формы эти поля не будут переданы (если их совсем убрать с формы), то при сравнении $_GET['arg'] === '' возникнет ошибка.
У меня вопрос такой. После перезагрузки браузера перестал работать код. До этого работал. И другие варианты кода в коментах тоже не работают. В чем может быть причина?
Проверку на то, что аргументы переданы стоит делать с помощью isset($_GET['arg']). Потому что если с формы эти поля не будут переданы (если их совсем убрать с формы), то при сравнении $_GET['arg'] === '' возникнет ошибка.
Проверку на то, что аргументы переданы стоит делать с помощью isset($_GET['arg']). Потому что если с формы эти поля не будут переданы (если их совсем убрать с формы), то при сравнении $_GET['arg'] === '' возникнет ошибка.
Делить ноль на что угодно - можно. Это корректное поведение и результатом будет 0. Калькулятор не показывает ошибки при такой операции, нужно просто вывести 0 в результате. То же и с умножением.
Делить что угодно на ноль - будет неопределенность (в пределе - бесконечность). И тут уже нужно показывать ошибку.
Проверку на то, что аргументы переданы стоит делать с помощью isset($_GET['arg']). Потому что если с формы эти поля не будут переданы (если их совсем убрать с формы), то возникнет ошибка.
if ($x1 == null || $x2 == null) {
return 'Ошибка! Аргумент 1 или аргумент 2 не передан!';
}
на
if (!isset($x1) || !isset($x2)) {
return 'Ошибка! Аргумент 1 или аргумент 2 не передан!';
и теперь если я не завожу какой-нибудь из аргументов, то мне возвращается "Ошибка! Введите число!" хотя по моим расчетам должно вернуться "Ошибка! Аргумент 1 или аргумент 2 не передан!". Сижу и пока что не могу понять почему так.
Удалил инпут, отправил запрос без аргумента и вот тут мне вернулось "Ошибка! Аргумент 1 или аргумент 2 не передан!", но потом вернув обратно опять тоже самое.
Почему здесь ошибка?
Потому что если на форме нет инпута с именем x1, то этого значения не будет в массиве $_GET. А если обратиться к несуществующему элементу, то будет ошибка.
Вместо $_GET[x1] должно быть $_GET['x1']. В качестве ключа должны использоваться строки! Вы же используете что-то, что интерпретатор пытается распознать как константу. Но такой константы не находит и поэтому берет строку с её названием. Но так делать не надо, это не очевидно и работает медленнее чем при явном использовании строк.
Куда делись проверки на то, что эти значения в массиве $_GET вообще есть? Я вас такому не учил.
По второму пункту ничего не исправили. Где проверка на то, что такие ключи в массиве вообще есть? Если с формы убрать сейчас input x1, и отправить запрос, то на строке
$firstOperand = $_GET['x1'];
возникнет ошибка. Из-за того что нет в массиве такого ключа.
Чтобы этого избежать нужно проверять это с помощью isset, empty или array_key_exists. ОБЯЗАТЕЛЬНО!
Зря убрали проверку. Запрос на бэкенд может прийти не только с вашей формы. И тогда всё пропало. Проверка обязательна! И на то, что в массиве $_GET есть ключи x1 и x2, и на то, что есть operation.
Также нет проверки на то, что x1 и x2 - числа.
<?php
if (empty($_GET)) {
return 'Ничего не передано!';
}
if (empty($_GET['operation'])) {
return 'Не передана операция';
}
if (empty($_GET['x1']) || empty($_GET['x2'])) {
return 'Не переданы аргументы';
}
if (($_GET['number1'] == '') || ($_GET['number2'] == '')) {
return "Допустимо вводить только числа";
}
$x1 = $_GET['x1'];
$x2 = $_GET['x2'];
$expression = $x1 . ' ' . $_GET['operation'] . ' ' . $x2 . ' = ';
switch ($_GET['operation']) {
case '+':
$result = $x1 + $x2;
return $result;
case '-':
$result = $x1 - $x2;
return $result;
case '*':
$result = $x1 * $x2;
return $result;
case '/':
if ($x2 == 0) {
return 'Деление на 0 невозможно';
break;
}
$result = $x1 / $x2;
return $result;
default:
return 'Операция не поддерживается';
}
Сделал всё, кроме 0. Я думаю, что 0 не воспринимается как число, т.к. трактуется интерпретатором как 'false', но ничего не смог сделать. Подскажите мою ошибку
не совсем понял is_numeric отсекает все те некорректные значения которые отсекает isset плюс отсекает строки зачем еще проверять isset-ом?
данных ключей в массиве нет - вы имели в виду вообще отсутсвие ключей в массиве или то что у этих ключей отсутствует значение? эти ключи в массиве есть но с пустыми значениями
Я имел в виду полное отсутствие ключей. Как если эти поля вообще убрать с формы, а затем отправить запрос. Поверьте, на реальном сайте найдутся пользователи, которые именно так и сделают.
Вопросы:
1)Правильно ли я понял, что GET и POST преобразует все в строки?
2)Когда я заполняю форму то на странице результата я вижу такую ссылку http://calculate.loc/result.php?numOne=3&index=%2B&numTwo=4
а если убрать все данные и ввести вот так http://calculate.loc/result.php, мне выдаст кучу ошибок, ведь форму получается просто проигнорили)
Это норм или мой любимый калькулятор смогут взломать как картонную коробочку?)
3)Почему в условии if вы пишите return a не echo? И как вообще return выводит строки, когда он только должен возвращать?))
Домашнее задание
Чтобы калькулятор принимал только числа, я на страницу с html формой поменял атрибут на type="number";
Поэтому данные, приходящие с форнтенда, всегда нужно проверять. Не должно быть ошибок, в уроке мы добавляли проверки на наличие параметров в запросе.
Ознакомьтесь с тем, как работают require и include в связке с return
Валидация на форме это хорошо, но обязательно надо проверять запрос на стороне бэкенда. Для проверки стоило использовать функцию is_numeric. В остальном все хорошо.
А как быть, если я хочу воспользоваться методом GET, а не POST. И пытаюсь сделать форму, в которую можно будет записать числа и получить результат на той же страничке? При таком написании все результаты равны нулю. Что я делаю не правильно?
Функция empty() возвращает true, когда переменная не существует и имеет пустое или нулевое значение. Поэтому в данном примере следует использовать проверку только на null (Например функция is_null()).
При делении на 0 вызывается Warning: Division by zero. Следует отлавливать передачу "0" второму аргументу, когда выбрана операция деления.
При передаче в качестве аргумента строки будет выводится Warning: A non-numeric value при выполнении арифметических выражений. Чтобы отловить передачу нечисловой строки можно воспользоваться функцией is_numeric().
<?php
if (empty($_GET)){
return 'Ничего не передано';
}
if (empty($_GET['operation'])){
return 'Не передана операция';
}
if (is_null($_GET['x1']) || is_null($_GET['x2'])){
return 'Не переданы аргументы';
}
if (!is_numeric($_GET['x1']) || !is_numeric($_GET['x2'])) {
return 'Используйте в качестве аргументов только числа';
}
$x1 = $_GET['x1'];
$x2 = $_GET['x2'];
switch ($_GET['operation']) {
case '+':
$result = $x1 + $x2;
break;
case '-':
$result = $x1 - $x2;
break;
case '*':
$result = $x1 * $x2;
break;
case '/':
if ($x2 == 0){
return 'На 0 делить нельзя';
}
$result = $x1 / $x2;
break;
default:
return 'Операция не поддерживается';
}
return $x1 . $_GET['operation'] . $x2 . ' = ' . $result;
5.
Улучшить.. Хорошо бы проверку на корректность ввода добавить еще на стороне клиента, дабы не обращаться к серверу, если пользователь накосячил. При этом проверку на серве тоже следует оставить на тот случай, если проверка в клиентской части косячная.
Еще можно использовать функцию number_format($result, 2), чтобы задать точность и избежать проблем при выполнении операций с дробными числами. Чтобы 36-35.99 равнялось 0.01, а не 0.009999999999998 :D
Они могут не придти, если их убрать на форме. Это может сделать любой посетитель сайта. Более того, он может сделать форму хоть прямо у себя на компе и отправлять запрос на ваш сервис. А сервис будет тонуть в ошибках.
Да, какой-то шлак. Даже объяснить не могу, зачем сделал это. Сейчас проверил и понял, что не работает. Когда ввожу ноль в форму не видит этот аргумент, и не по причине этого условия. Я попытался использовать несколько вариантов с нулём(пробовал в условии null, пробовал в условии 0, пробовал функцию isset для проверки на отличие от null) и результат не меняется: всегда игнорит ноль. Если убрать второе условие, ноль всё равно не видит, а операцию деления на ноль выполняет. Магия прям. Пытался разобраться чем отличается ноль и null, понял только, что разница в том, что 0 - число, null - переменная без значения, и всё же вопрос почему в строке не определена переменная не разрешился. Короче, HELP!
null - это отсутствие какого-либо значения. 0 - это числовое значение.
isset(0) вернёт true. В то же время isset отлично подходит для проверки того, есть ли ключ в массиве - isset($array['some_key']). Для нашего случая подходит, в отличие от empty, который вернёт true, как для null, так и для 0, так и для пустой строки.
Если с формы убрать поля x1 и x2, то скрипт будет падать с ошибкой. Такого допускать нельзя. Нужно обязательно проверить на бекенде, что данные пришли.
if (empty($_GET['operation'])) {
return 'Не передана операция.';
}
if ($_GET['x1'] === '' && $_GET['x2'] === '') {
return 'Ничего не передано.';
}
if ($_GET['x1'] === '' || $_GET['x2'] === '') {
return 'Один из аргументов не передан.';
}
if (!isset($_GET['x1']) || !isset($_GET['x2'])) {
return 'Один из аргументов не передан.';
}
if (!is_numeric($_GET['x1']) || !is_numeric($_GET['x2'])) {
return 'Только числа в качестве аргументов.';
}
$x1 = $_GET['x1'];
$x2 = $_GET['x2'];
$expression = $x1 . ' ' . $_GET['operation'] . ' ' . $x2 . ' = ';
switch ($_GET['operation']) {
case '+':
$result = $x1 + $x2;
break;
case '-':
$result = $x1 - $x2;
break;
case '*':
$result = $x1 * $x2;
break;
case '/':
$result = $x2 != 0 ? ($x1 / $x2) : 'На ноль делить нельзя';
break;
default:
return 'Операция не поддерживается';
}
return $expression . $result;
Дубль 3. Проверки на бекенде нужно делать железно и для этого мы и используем функции is_numeric и isset(в данном случае) и если что-нибудь поменяется во фронте, эти функции отработают, так? Я попробовал убрать в input-ах имена переменных и в случае без isset возвращает вариант с is_numeric. После добавления isset, возвращает вариант с ним, стало быть проверяет, что данные есть. Результат не считает(вероятно потому, что убрав имена из полей мы прописанную логику нарушили) но и ошибку не выдаёт: так и должно быть? Ещё я попробовал после возвращения имен в полях закомментировать isset и ноль как число работает. Вероятно из-за того, что я убрал проверки с empty, ноль теперь работает, даже если закомментировать всё, кроме ['operation']. Когда делал задание используя empty, бился долго и не знал, что и 0, и пустую строку, и null, empty возвращает со значением true. Читал доку и как-то невнимательно, видать. После Ваших замечаний понял, почитал доку ещё - закрепил. Простите, что так много текста, просто пытаюсь разобраться, чтоб дальше не тормозить. Такое решение нормальное?
Ошибку не выдаёт. Может у меня что-то не подключено? Хотя по предыдущим урокам всё как по маслу шло, только я тупил) Видать, что-то не то делаю или не понимаю что сделать. Если я уберу поля из формы(HTML), то как введу данные?) или речь о полях с пустыми строками в условиях?
Речь о том, что данные и не надо вводить. Представь, что пользователь взял и изменил форму и удалил поля. Прямо в браузере это можно сделать. А потом взял и отправил кривой запрос, просто чтобы поломать скрипт. Поля вообще не придут в запросе и когда ты напишешь
$x1 = $_GET['x1'];
то тут возникнет ошибка, так как такого ключа в массиве попросту нет. Если ошибки не видишь, значит их вывод у тебя выключен и нужно их включить в php.ini.
error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT
display_errors = On
display_startup_errors = On
log_errors = On
Ведь так должно быть? Это я скопировал из своего php.ini. Погуглил, вроде похоже) Везде практически одинаковые советы. И ошибки при этом не выдает. Мне нужно использовать проверку на то, что GET вообще пуст?
if (empty($_GET)) {
return 'Ничего не передано.';
}
И с ним выдаёт ошибку 404. Если сменить путь на просто <form action="result.php">, то всё работает, НО не почему-то в файле result.php работает только
$result = require __DIR__ . '/calc.php';
и если сменить на $result = require DIR . 'calc.php';, то выдаст ошибку:
Страница недоступнаСайт localhost пока не может обработать этот запрос.
HTTP ERROR 500
Все файлы находятся в 1ой директории, в одной папке
Путь из атрибута action формы используется браузером, это то, что в адресной строке. А то что через require - это путь на сервере. Это абсолютно разные вещи!
Ты index.php в браузере по какому адресу открываешь?
К сожалению, нет. Занимаюсь на работе, на рабочем пк ( да, звучит странно) тут стоит iis express. На днях собираюсь брать ноут для себя, и вот тогда уже поставлю open server)
Ты инпуты вообще удалил с формы, и нет ошибок? Значит они выключены и их надо включить в php.ini. Потому что происходит обращение к элементу массива по несуществующему ключу. А это ошибка уровня Notice.
Нужно сначала проверить что x1 и x2 пришли в запросе. Если их убрать с формы и отправить запрос, это должно корректно обработаться. А сейчас возникнет ошибка. Смотрите в сторону empty/isset.
<?php
if (empty($_GET)) {
return 'Ничего не переданно';
}
if (empty($_GET['operation'])) {
return 'Операция не переданна';
}
if (isset($_GET['x1']) && isset($_GET['x2'])) { //Задание 5. Сам не додумался, подсмотрел у других
$x1 = $_GET['x1'];
$x2 = $_GET['x2'];
} else {
return 'Ошибка в неполной передаче данных, должны быть переданы 2 числа';
}
if ($_GET['x1'] == '' || $_GET['x2'] == '') { //Задание 1.
return 'Аргументы 1 или 2 не переданы';
}
if (!is_numeric($_GET['x1']) || !is_numeric($_GET['x2'])) { //Задание 4.
return 'Введите корректные числа';
}
$operation = $_GET['operation'];
$expression = $x1 . ' ' . $operation . ' ' . $x2 . ' = ';
switch ($operation) {
case '+':
$result = $x1 + $x2;
break;
case '-':
$result = $x1 - $x2;
break;
case '/': //Задание 3.
if ($x2 == '0') {
return 'На ноль делить нельзя';
} else {
$result = $x1 / $x2;
}
break;
case '*': //Задание 2.
$result = $x1 * $x2;
break;
default:
return 'Операция не поддерживается';
}
return $expression . $result;
Сперва полез в index.php сменить тип с text на number, но понял что это не то. Т.к. дробные числа не получиться написать.
Кстати, а есть ли необходимость в первых двух условиях, если и так все условия обработаны?
1) Функция empty получила значение '0', а данное значение для нее является пустым, поэтому выдало сообщение 'Введите числа'. Поменял функцию empty на isset
2) Сделал. Добавил в два input'a в index.php и два case в calc.php
3) Вышла ошибка warning о делении на ноль. Добавил дополнительное условие
4) Вышла ошибка warning обнаружено нечисловое значение. Изменил тип для input'a, с text на number и добавил атрибут step="any", чтобы считать числа float
5) a) В option у нас нет пустого значения, поэтому условие operation можно убрать
b) В файле calc.php можно вначале добавить переменные для x1, x2 и operation, чтобы код легче читался
c) Из switch убрать default, т.к. операция будет выбрана в любом случае
d) Можно добавить еще операторы для вычислений
Сначала обратились к элементам массива, затем проверили их существование. Это грубая ошибка, которая приведет к ошибкам кода. Если убрать с формы x1 и x2 и отправить запрос, то всё рухнет в ошибках.
isset не проверяет, являются ли переданные значения числами. Если передать буквы, опять же будет ошибка.
Изменил тип для input'a, с text на number и добавил атрибут step="any", чтобы считать числа float
Этого недостаточно. Любой злодей может изменить форму как ему угодно, прямо у себя в браузере. Нужно всегда валидировать значения на бекенде.
В option у нас нет пустого значения, поэтому условие operation можно убрать
И снова можно изменить форму через инструменты разработчика/создать новую у себя локально и отправлять запросы, ломающие скрипт. Ни к чему хорошему это не приведет.
Из switch убрать default, т.к. операция будет выбрана в любом случае
Уже лучше, только теперь другая ошибка на этой же строке. Если мы передадим в качестве аргументов нули, то программа на этом месте остановится и скажет "Не переданы аргументы". Хотя это абсолютно нормальные аргументы, являющиеся числами. Калькулятор позволяет складывать нули.
Понял. Изменил на 'Делить на ноль нельзя'.
Ещё вопрос по поводу isset, он смотрит конкретно на то что бы в х1 и х2 было наполнение или в целом на существование такой детали массива?
А я прочел, даже много раз, до меня просто долго доходило))
У меня такое бывает, но сейчас уже разобрался что к чему, спасибо.
Как я понял isset проверяет существование переменной, либо ключа в массиве, но не обращает внимание на присутствие "содержимого" и в случаях с:
$hello = 'привет';
или
$hi='';
В обоих случаях isset вернет true
Верно?
'' - это пустая строка. Отсутствие значения - это null. И вот на нём isset уже вернёт false. Не нужно использовать термин "содержимое". Используйте термин "значение".
Ну ёлки-палки! Ну где вы увидели, чтобы писали конструкции if-else без фигурных скобок? Пишите их всегда, придерживайтесь того же стиля, что и в моих уроках. Рано вам было это говорить, но раз уж копируете код не пойми откуда, то ознакомьтесь со стандартами PSR. И всегда следуйте им при оформлении. Я в своих уроках их всегда придерживаюсь, откуда вы умудряетесь хватать такие ужасные примеры?
Да) Возможно, вы до этого изучали другие языки, или смотрели устаревшие материалы по PHP. Но пожалуйста, старайтесь придерживаться такого же стиля, что я даю в своих уроках. Он на данный момент актуален.
Подскажи пожалуйста, как сделать, чтоб результат отображался на этой же странице, где сама форма в index.php?
Т.е. ставим перед кнопкой Посчитать знак "=" и выводим результат тут же, при клике на кнопку Посчитать.
Я попробовал просто в index.php сделать подключение:
Но потом меня сбило с толку, что делать с form action="" что тут писать тогда?!
Правильно ли вообще я думаю? В данном случае после подключения файла выводится ошибка: https://cloud.mail.ru/public/EL5G/U99mFpcYx
и в результат сразу выводит информацию, даже не кликнув по кнопке Посчитать
В данном случае после подключения файла выводится ошибка: https://cloud.mail.ru/public/EL5G/U99mFpcYx
и в результат сразу выводит информацию, даже не кликнув по кнопке Посчитать. Как это исправить?
Нужно проверять что необходимые данные пришли в запросе, и только потом подключать файл, как вариант. В ошибке же всё написано. Нужно обрабатывать запрос.
Эта переменная объявляется только если пришел запрос с query-параметрами, а ты ее используешь всегда, даже когда запрос без параметров. О чем в ошибке и написано.
добрый день, сам сделал только 1 и 2, третье подсмотрел, всё как у всех, так что флудить не буду. Ломал голову пару вечеров по поводу третьего, но прежде чем писать код на 10 стр. решил подглядеть, оказалось, что всего то одна строка как тут case '/' :
$result = $x2 != 0 ? ($x1 / $x2) : 'На ноль делить нельзя';
break;
Почему в итоге выводите как $result если поделили на 0? Это ведь ошибка, значит нужно сразу сделать return, а у вас программа продолжает выполняться как ни в чем не бывало. И повторюсь еще раз - не нужно в одну и ту же переменную складывать разные типы данных. $result - для числа, а вы туда текст ошибки пихаете.
Например да. Но конкретно по вашему коду достаточно выше этих строк вынести проверку с использованием array_key_exists. Жаль, что самостоятельно не получилось у вас к этому придти. Поправьте и пришлите исправленный вариант.
<?php
if (empty($_GET)) {
return 'Ничего не передано!';
}
if (empty($_GET['operation'])) {
return 'Не понимаю, что делать';
}
if (!isset($_GET['x1']) || !isset($_GET['x2'])) {
return 'Как минимум один из аргументов пуст';
}
$x1 = $_GET['x1'];
$x2 = $_GET['x2'];
$expression = $x1 . ' ' . $_GET['operation'] . ' ' . $x2 . ' = ';
switch ($_GET['operation']) {
case '+':
$result = $x1 + $x2;
break;
case '-':
$result = $x1 - $x2;
break;
case '*':
$result = $x1 * $x2;
break;
case '/':
$result = $x1 / $x2;
break;
default:
return 'Операция не поддерживается';
}
#деление на 0:
if ($_GET['x2'] == 0 and $_GET['operation'] == '/') {
return 'На ноль делить нельзя!';
}
#Вводим только числа:
if ($_GET['x1'] !== preg_match("[0-9]", '') or $_GET['x2'] !== preg_match("[0-9]", '')) {
return 'С тем, что Вы ввели, в математику нельзя!';
}
return $expression . $result;
?>
Можно добавить возведение в степень и прочие более сложные операции.
Можно нарисовать кнопки, чтобы в них можно было тыкать, вместо того, чтобы вводить инпуты (ну, мало ли, у человека только мышь есть)
Сломать можно, думаю, слишком длинным вводом
Здравствуйте, форма передаёт GET запрос в result.php, почему вам удалось получить все аргументы GET запроса из другого файла(вызывая $_GET в calc.php), почему не возникло ошибки?
<?php
if (empty($_GET)) {
return 'Ничего не передано!';
}
if (empty($_GET['operation'])) {
return 'Не передана операция';
}
//Дополните код так, чтобы можно было передавать 0.
if (!isset($_GET['x1']) || !isset($_GET['x2']) || !isset($_GET['operation'])){
return 'Не переданы ключи';
}
$x1 = $_GET['x1'];
$x2 = $_GET['x2'];
if ($x1 === '' || $x2 === '') {
return 'Не переданы аргументы';
}
//Разделитель дробной части может быть ','. Заменим ',' на '.' (например, 0,6=0.6).
if (stristr($x1, ",") != false) {
$x1 = str_replace( ",", ".", $x1);
}
if (stristr($x2, ",") != false) {
$x2 = str_replace(",", ".", $x2);
}
//Чтобы в качестве аргументов можно было отправить только числа.
if (!is_numeric($x1)) {
return 'Первое значение не число';
} else {
$x1 = floatval($x1); //приводим к float
}
if (!is_numeric($x2)) {
return 'Второе значение не число';
} else {
$x2 = floatval($x2); //приводим к float
}
//Зачем приводим к float:
//Если вводим, например, 00000.3 или .3, то программа это воспринимает как 0.3 и выполняется
//Результат вычислений: 00000.3 + 4 = 4.3 или .3 + 4 = 4.3
//Т.е. при выводе нужно заменить 00000.3 и .3 на 0.3
$expression = $x1 . ' ' . $_GET['operation'] . ' ' . $x2 . ' = ';
switch ($_GET['operation']) {
case '+':
$result = $x1 + $x2;
break;
case '-':
$result = $x1 - $x2;
break;
case '*':
$result = $x1 * $x2;
break;
case '/':
if ($x2 != 0) {
$result = $x1 / $x2;
} else {
return 'На 0 делить нельзя!';
}
break;
default:
return 'Операция не поддерживается';
}
return $expression . $result;
Пыталась с помощью strpos проверить есть ли "," в строке.
strpos(',7', ',') != false будет false
strpos('0,7', ',') != false будет true
Почему так происходит?
Если убрать полностью поле x1 с формы и отправить запрос, то в массиве $_GET просто не будет ключа x1.
Далее произойдёт следующее - empty($_GET['x1']) вернёт true, так как за ним следует логический оператор &&, интерпретатор пойдет вычисляет значение справа от этого оператора и вот здесь:
$_GET['x1'] != '0'
Произойдёт ошибка, потому что вы обратились по несуществующему ключу.
Сначала нужно удостовериться, что вообще ключ в массиве есть. Это можно сделать либо с помощью isset, либо с помощью array_key_exists.
if (!isset($_GET['x1']) || !isset($_GET['x2']) || !isset($_GET['operation'])){
return 'Не переданы ключи';
Какие ключи? Нужно больше деталей.
А для operation выше уже проверили с помощью isset.
if ($x1 === '' || $x2 === '') {
return 'Не переданы аргументы';
}
Для чего эта проверка, если ниже проверим на то, что это числа.
if (stristr($x1, ",") != false) {
Для строк используются одинарные кавычки. Зачем использовать функцию не по назначению? Для поиска символов используйте strpos. Сравнивать при этом нужно строго, то есть с !== а не !=, чтобы избежать приведения нуля к false.
Сначала нужно проверить, что в массиве вообще есть такой ключ. Иначе будет ошибка.
Да и вообще непонятно для чего тут теги обрезать, если должна быть проверка на числа. Она их и так не пропустит.
<?php
$argumentOne = $_GET['argumentOne'];
$argumentTwo = $_GET['argumentTwo'];
$operation = $_GET['operation'];
if (empty($_GET)){
return 'Nichego ne peredano';
}
if (empty($operation)){
return 'Operaciya ne vibrana';
}
if ($argumentOne === '' || $argumentTwo === ''){
return 'Argumenti ne peredani';
}
if (!is_numeric($argumentOne) || !is_numeric($argumentTwo)) {
return 'Neverniy format';
}
$display = $argumentOne .' '. $operation .' '. $argumentTwo . ' = ';
switch ($operation) {
case '+':
$result = $argumentOne + $argumentTwo;
break;
case '-':
$result = $argumentOne - $argumentTwo;
break;
case '*':
$result = $argumentOne * $argumentTwo;
break;
case '/':
if($argumentTwo == 0){
return 'na 0 delit nelza';
} else {
$result = $argumentOne / $argumentTwo;
}
break;
}
return $display . $result;
Такой вот вопрос: В чем разница между проверкой на ввод числа на фронте и бэке ? Лучше ставить type="number" в инпуте, или всё же проверять с помощью php?
$argumentOne = $_GET['argumentOne'];
$argumentTwo = $_GET['argumentTwo'];
$operation = $_GET['operation'];
if (empty($_GET)){
return 'Nichego ne peredano';
}
Ну ага, сначала обратились к потенциально несуществующим ключам массива, а потом проверили его на пустоту. В итоге если поле из формы убрать и отправить запрос, то можно утонуть в ошибках.
<?php
if (empty($_GET)) {
return 'Ничего не найдено';
}
if (empty($_GET['operation'])) {
return 'Не передана операция';
}
if (empty($_GET['x1']) || empty($_GET['x2'])) {
if ($_GET['x1'] != 0 & $_GET['x2'] != 0) {
return 'Не переданы аргументы';
}
}
if (!is_numeric($_GET['x1']) || !is_numeric($_GET['x2'])) {
return 'Вы вводите не числа, внимательнее!';
}
$x1 = $_GET['x1'];
$x2 = $_GET['x2'];
$expression = $x1 . ' ' . $_GET['operation'] . ' ' . $x2 . ' = ';
switch ($_GET['operation']) {
case '+':
$result = $x1 + $x2;
break;
case '-':
$result = $x1 - $x2;
break;
case '*':
$result = $x1 * $x2;
break;
case '/':
if ($x2 != 0) {
$result = $x1 / $x2;
break;
} else {
$result = 'Деление на 0! Ужасно!';
break;
}
default:
return 'Operation is not defined';
}
return $expression . $result;
Я вот сделал так и решительно не понимаю, что можно улучшить, кроме уж совсем совершенствования калькулятора для подсчета, например, длинного выражения, но такое я пока не умею делать(
if ($_GET['x1'] == '' || $_GET['x2'] == '') {
return 'Не переданы аргументы';
Если аргументы вообще не передать (удалить их с формы и отправить такой запрос), то будет ошибка, потому что таких ключей в массиве не будет.
} else {
$result = 'Деление на ноль запрещено';
}
Тогда уж return, по аналогии с другими ошибками.
Валидация на фронте не спасет, я могу прямо в браузере ее поменять как хочу, в консоли разработчика. Нужно проверять, что это число именно на бэке, и делать это всегда.
return 'Операция '.$_GET['operation'] .' не поддерживается';
Опасно выводить вот так любые данные, прилетевшие с фронта, там может быть вредоносный XSS-код
if ($_GET['x1'] == '' || $_GET['x2'] == '') {
return 'Не переданы аргументы';
заменил на:
if (count($_GET) != 3 ) {
return 'Не переданы аргументы';
}
if (!is_numeric($_GET['x1']) || !is_numeric($_GET['x2'])) {
return 'Аргументы не являются числами';
}
я не придумал пока что другого варианта,
тут же учёл проверку "Является ли аргумент числом".
} else {
$result = 'Деление на ноль запрещено';
}
изменил на:
} else {
return 'Деление на ноль запрещено';
}
return 'Операция '.$_GET['operation'] .' не поддерживается';
Еще раз повторюсь. Если аргументы вообще не передать (удалить их с формы и отправить такой запрос), то будет ошибка, потому что таких ключей в массиве не будет. Нельзя брать и обращаться к ключам массива, пока не убедились, что они там есть. Пока это не исправите дальше даже смотреть не буду.
if (!array_key_exists('x1', $_GET) || !array_key_exists('x1', $_GET)) {
return 'Не переданы аргументы';
}
if (!is_numeric($_GET['x1']) || !is_numeric($_GET['x2'])) {
return 'Аргументы не являются числами';
проверил работу при удалении аргумента(ов) из формы
"Не переданы аргументы". Это получилось из за того что выражение:
if (empty($_GET['x1']) || empty($_GET['x2'])) {
return 'Не переданы аргументы';
}
выполнилось, потому что функция empty($_GET['x1'] вернула TRUE, а функция empty(): Возвращает FALSE, если переменная существует и содержит непустое ненулевое значение. В противном случае возвращает TRUE. Мы передали в нее 0, соответственно она вернула TRUE.
Исправить можно так:
if ((empty($_GET['x1']) && $_GET['x1'] != 0) || (empty($_GET['x2']) && $_GET['x2'] != 0)) {
return 'Не переданы аргументы';
}
2.
<?php
if (empty($_GET)) {
return 'Ничего не передано!';
}
if (empty($_GET['operation'])) {
return 'Не передана операция';
}
if (empty($_GET['x1']) || empty($_GET['x2'])) {
if ($_GET['x1'] != 0 || $_GET['x2'] != 0) {
return 'Не переданы аргументы';
}
}
$x1 = $_GET['x1'];
$x2 = $_GET['x2'];
$expression = $x1 . ' ' . $_GET['operation'] . ' ' . $x2 . ' = ';
switch ($_GET['operation']) {
case '/':
$result = $x1 / $x2;
break;
case '*':
$result = $x1 * $x2;
break;
case '+':
$result = $x1 + $x2;
break;
case '-':
$result = $x1 - $x2;
break;
default:
return 'Операция не поддерживается';
}
return $expression . $result;
После Вашого вопроса задумался и понял, что это лишнее. Если в filter_input подать строку, то переменной присвоит значение null. А это неправильно. Я правильно понял свою ошибку?
Да, но лучше исправляйте и потом уже спрашивайте, потому что иногда выходит так что говорим вроде бы об одном с учениками, а они имеют в виду совсем другое
Самостоятельно получилось выполнить где-то только 50%, пришлось прибегнуть к помощи комментов.
Урок очень понравился. Из усовершенствований хотелось бы чтоб дробные числа вводились через "," как в стандартном калькуляторе.
<?php
if (empty($_GET)) {
return 'Ничего не передано!';
}
if (empty($_GET['operation'])) {
return 'Не передана операция';
}
if (!isset($_GET['x1']) || !isset($_GET['x2'])) {
return 'Не переданы аргументы';
}
if (!is_numeric($_GET['x1']) || !is_numeric($_GET['x2'])) {
return 'Введите числа! (для ввода дробной части используйте знак ".")';
}
$x1 = $_GET['x1'];
$x2 = $_GET['x2'];
$expression = $x1 . ' ' . $_GET['operation'] . ' ' . $x2 . ' = ';
switch ($_GET['operation']) {
case '+':
$result = $x1 + $x2;
break;
case '-':
$result = $x1 - $x2;
break;
case '*':
$result = $x1 * $x2;
break;
case '/':
$result = $x2 != 0 ? $x1 / $x2 : 'На ноль делить нельзя!';
break;
default:
return 'Операция не поддерживается';
}
return $expression . $result;
Сам смог добавить умножение и деление. При возведении в степень в результате появлялся пустой квадратик. Поэтому не стал добавлять. Урок понравился очень. Форматирую с Ctrl+Alt+L. Я просто делаю copy-paste своего кода в комменты. Может из-за этого нарушается форматирование?
Если передать 0, то пишет, что не переданы аргументы. Это происходит потому, что функцией empty cледующие значения воспринимаются как пустые:
"" (пустая строка), 0 (целое число), 0.0 (число с плавающей точкой), "0" (строка), NULL, FALSE, array() (пустой массив)(цитата из официальной документации). Решил проблему конструкцией !isset, предварительно почитав комменты :) Если поделить на ноль, то "результат вычислений:
10 / 0 = INF". Исправил. Если добавить строку, калькулятор не работает корректно. Исправил.
<?php
if (!isset($_GET)) {
return 'Ничего не передано!';
}
if (!isset($_GET['operation'])) {
return 'Не передана операция';
}
if (!isset($_GET['x1']) || !isset($_GET['x2'])) {
return 'Не переданы аргументы';
}
if ($_GET['x2'] == 0 && $_GET['operation'] == '/') {
return 'На ноль делить нельзя!';
}
if (!is_numeric($_GET['x1']) || !is_numeric($_GET['x2'])) {
return 'Можно вводить только числа!';
}
$x1 = $_GET['x1'];
$x2 = $_GET['x2'];
$expression = $x1 . ' ' . $_GET['operation'] . ' ' . $x2 . ' = ';
switch ($_GET['operation']) {
case '+':
$result = $x1 + $x2;
break;
case '-':
$result = $x1 - $x2;
break;
case '*':
$result = $x1 * $x2;
break;
case '/':
$result = $x1 / $x2;
break;
default:
return 'Операция не поддерживается';
}
return $expression . $result;
При передаче 0 функция empty воспринимает его как пустое значение, поэтому (уже после того как прочитал комменты и дополнительный урок) добавил isset.
При делении на ноль, то выводится 3 / 0 = INF, добавил для этого условие if
При вводе строки калькулятор работает не совсем корректно, добавил для этого условие if с функцией is_numeric
В качестве улучшения можно добавить распознавание запятой в десятичных дробях или добавление кнопок вместо самостоятельного ввода, больше никаких улучшений не надумал.
<?php
if (empty($_GET)) {
return 'Ничего не передано';
}
if (empty($_GET['operation'])) {
return 'Не передана операция';
}
if (!isset($_GET['x1']) || !isset($_GET['x2'])) {
return 'Не переданы аргументы';
}
if (!is_numeric($_GET['x1']) || !is_numeric($_GET['x2'])) {
return 'Необходимо ввести число';
}
$x1 = $_GET['x1'];
$x2 = $_GET['x2'];
$expression = $x1 . ' ' . $_GET['operation'] . ' ' . $x2 . ' = ';
switch ($_GET['operation']) {
case '+':
$result = $x1 + $x2;
break;
case '-':
$result = $x1 - $x2;
break;
case '/':
if ($x2 == 0) {
return 'Ошибка, деление на ноль';
}
$result = $x1 / $x2;
break;
case '*':
$result = $x1 * $x2;
break;
default:
return 'Операция не поддерживается';
}
return $expression . $result;
Возник так же вопрос - какую литературу стоит читать касательно PHP и стоит ли вообще? Просто слышал такое мнение от людей, которые себя программистами называли, что читать по программированию ничего не стоит и чуть ли не бесполезно
Исправил, вместо сравнения использовал empty.
Да, в codingzone я увидел образцовое решение, просто не могу понять, стоит ли писать такой код, который только из встроенных функций и состоит или лучше все-таки какую-то часть писать самому, не полагаясь на функции.
<?php
if (empty($_GET)) {
return 'Ничего не передано!';
}
if (empty($_GET['operation'])) {
return 'Не передана операция';
}
if ($_GET['x1'] === '' || $_GET['x2'] === '') {
return 'Не переданы аргументы';
}
if (!is_numeric($_GET['x1']) || !is_numeric($_GET['x2'])) {
return 'Передано не число';
}
$x1 = $_GET['x1'];
$x2 = $_GET['x2'];
$expression = $x1 . ' ' . $_GET['operation'] . ' ' . $x2 . ' = ';
switch ($_GET['operation']) {
case '+':
$result = $x1 + $x2;
break;
case '-':
$result = $x1 - $x2;
break;
case '*':
$result = $x1 * $x2;
break;
case '/';
if ($x2 == 0){
return 'на ноль делить нельзя!';
} else {
$result = $x1 / $x2;
}
break;
default:
return 'Операция не поддерживается';
}
return $expression . $result;
Что можно улучшить, не знаю. Может сделать вывод результата на той же страничке, где вводим числа? Чтоб при нажатии кнопки "посчитать" справа выводился ответ?
Добрый день, я прошла указанный урок. Но не понимаю, где у меня допущены ошибки. Если не брать во внимание упрощение через filter_input и приведение к типу float, то основной обсуждаемой ошибкой в уроке было игнорирование isset. Но у меня он учтен. Поэтому могу попросить точно ткнуть пальцем, что тут не так?)
1)
2)
3)
Отлично! Все правильно.
Проверка на строку :
Не пойдёт, в переменной $_GET['что-то'] всегда будет строка. Попробуйте ещё варианты.
P.S. else здесь лишний: если условие выполнится, то сработает return и код дальше не будет выполняться. Достаточно писать:
4 в индексе
в calc.php
Очень хорошо, что позаботились о клиентской стороне! А ещё можно было проверить, является ли переданное значение числом с помощью is_numeric().
а можно использовать ctype_digit() вместо is_numeric()?
Тогда дробные числа не пройдут (содержат точку, а не только цифры)
Сделал, вроде все работает
Всё в общем-то очень хорошо)
Из улучшений:
Тогда при выполнении, там где происходит обращение к $_GET['x1'], возникнет ошибка.
Чтобы этого избежать, стоит воспользоваться функцией array_key_exists() или isset() - так вы сможете убедиться, что такой ключ в массиве существует. А если нет - напишете соответствующую ошибку.
Так?
Да, теперь все корректно. Но содержимое после if и else советую всегда помещать внутрь фигурных блоков, даже если это одна строка.
А switch можно написать вне if, это позволит избавиться от лишней вложенности. Просто сделайте проверку на ошибки отдельным условием:
Понимаете, что проще стало? Сначала проверили данные на корректность, а потом уже с ними спокойно работем, избегая слишком громоздких условий.
Все сделал, не знаю что еще добавить можно) все работает)
Всё супер. Только не понял, для чего вы внутри calc.php проверяете, что он существует. Это лишнее. Все остальное - огонь!
А в степень почему-то не получается с помощью pow, только ** - подскажите почему так?
Потому что в PHP нет функции pow(), но есть оператор ** =)
единственное. Проблему со string решил так:
<input type="number" name="number1">
<input type="number" name="number2">
Ок, всё норм. Речь шла о проверке на бэкенде - функция is_numeric() позволяет проверить, что в переменной именно числовое значение.
Пока так и не получилось прибавить 0. Пишу позже, может кому поможет. Разобрался, почему не получалось, потому-что проверял x1 и x2 на empty(), и если вводил 0, то php считал, что поле пустое
Ага, всё правильно, первое задание засчитано. А как в итоге сделал?
Спасибо за замечательный курс. Все получилось, но пришлось подсмотриват в ответах других участников.
Это абсолютно нормально, не забывайте в гугле и на stackoverflow тоже подглядывать.
По поводу 'Нельзя вводить строковые значения' - не совсем правда. В коде проверка только на то, что это не число. Это ещё не значит, что там строка. Правильнее будет сказать именно о том, что значения должны быть числовыми.
В остальном - отлично!
Спасибо! Учту!
Ты случаем не пропустил закрывающий тек </label> для id="operation"?
Проверка на пустоту $_GET и сопутствующее ему выполнение бессмысленны,т.к. селектор по умолчанию предлагает первый вариант и при нажатии кнопки посчитать, это значение передастся.
Для чего задавать label если мы оставляем их пустыми?
Нужно ли в логике в конструкции switch задавать default, если у нас селектор содержит только два варианта?
Да, label лишние, убрал. Спасибо.
Проверка на пустоту не бессмысленна - нельзя доверять тому, что придёт от клиента. Нет гарантии что пользователи будут отправлять данные на бекенд исключительно из "правильной" формы. Ничто не мешает им создать свою форму с плохими данными и завалить ваш бекенд ошибками.
В switch лучше всегда добавляйте секцию default - в ней можно обрабатывать внештатные ситуации, когда пришли данные, которых быть не должно.
Понял,спасибо! Отличный практический урок :)
Мой топовый код :D
Да, хорошо =)
Единственное, вместо
я бы написал:
Благодарю!
Если с формы сейчас убрать input x1 или x2, то скрипт посыпется с warning-ами, из-за того что в массиве $_GET вообще нет ключей x1 и x2. Попробуйте исправить.
Да, на сколько я знаю надо всегда проверять передаются ли параметры. Спасибо за замечание.
Видимо упустил когда редактировал этот код:
Окей, и еще один совет: всегда используйте фигурные кавычки для конструкций if-else, даже если это одна строка.
Если не будут переданы x1 или x2, будет ошибка, попробуйте исправить.
Вроде нет ошибки. А только предупреждение выводится: "Не переданы числовые аргументы!".
А если их совсем из формы убрать?
Да при пустых input'ах я проверял.
Вот здесь будет ошибка, если аргументы в форме вообще отсутствовали. Нужно проверять с помощью isset, затем проверить с помощью is_numeric, привести переменные к float, и только после этого сравнивать с 0 (не строкой, а числом).
is_numeric не гарантирует, что число будет именно целым, текст ошибки некорректен.
Будет ошибка, если поля в форме вообще отсутствовали, нужно проверять с помощью isset.
Хорошо!
Будет ошибка, если поля в форме вообще отсутствовали, нужно проверять с помощью isset.
Спасибо за урок! =)
Код из файла calc.php
На счет того что добавить/улучшить:
1)Когда я попробовал ввести 2 - -2 у меня выдало "Введите числа"
2)Степень, корень, факториал
Вот тут что-то не так:
Вот тут стоить использовать для проверки is_numeric (так как параметр из POST-запроса это почти всегда строка):
$x1 может быть нулем
Переделал
Если я передам два числа, отличные от нуля, то программа не будет работать. Вы хоть проверяйте, чтобы она хотя бы просто работала, прежде чем отправлять =)
Простите, я просто сидел в Универе на паре и почему-то подумал, что это вполне себе логичное решение =)
Вот робочий код ( как минимум у меня пашет =) )
Если на форме убрать поля x1 и x2, и отправить запрос, то скрипт вот здесь вывалит ошибку.
Но этот скрипт должен корректно работать, независимо от формы - нельзя доверять тому, что форма будет корректной. Поэтому нужно проверять сначала, пришли ли эти значения вообще или нет. Для этого можно использовать функцию isset().
От себя добавил чтобы при проверки на строку, очищал пробелы, так как интерпретатор сам приводит к числовым значениям даже если есть пробелы слева и справа
Весь код
isset возвращает true или false, не имеет смысла запихивать его внутрь empty().
В остальном - отлично!
Его использовал, чтобы интерпретатор обрабатывал как 0. А он определял, то ли как null, то ли еще как то. Оттолкнулся от того, что isset() проверяет на существование переменной и после этого нули уже отрабатываются, исходя из этих соображений использовал.
Не совсем корректное сообщение. Скорее так - "Аргументы должны быть числами".
вот что вышло после оптимизации
Другое дело. Не надо торопиться и скидывать первое, что пришло в голову) Еще стоить проверять с помощью isset, что переменные вообще пришли.
Почему бы просто не указать атрибут pattern для формы, чтобы только числа вводились? ))
Потому что форму может изменить любой желающий и поломать бекенд кривым запросом.
Добрый день!
Немного не понял 5 задание, но улучшил немного передавая переменную как htmlspecialchars:
Привет. Четвертый пункт задания требует сделать проверку на то, что x1 и x2 являются числами. Если это сделать, то не будет надобности в htmlspecialchars - просто числа не могут быть кодом.
Пятое задание читай так - как можно текущий код поломать (передав что-либо в форму, изменив форму)? Как это можно исправить?
Понял, при функции is_numeric и так уже ничего другого ввести не получится кроме чисел, а над тем как его можно поломать вечером подумаю)
array_key_exists - не нужно вызывать в цикле. Она сама пройдется по всему массиву.
Ок!
Привет! У меня вопрос по этому "Сделайте так, чтобы в качестве аргументов можно было отправить только числа." Я при создании своей формы установил четкий формат ввода, т.е. если пользователь накосячил в каких-то данных, окно все равно подсвечивается красным. В данном случае, при создании калькулятора, есть смысл устанавливать дополнительные ограничения на получаемые значения параметров из формы или достаточно того, что в форме они и так есть?
На стороне бэкенда должна быть своя проверка. Форму пользователь может изменить в своём браузере (например специально, чтобы все поломать).
Проверку на то, что аргументы переданы стоит делать с помощью isset($_GET['arg']). Потому что если с формы эти поля не будут переданы (если их совсем убрать с формы), то при сравнении $_GET['arg'] === '' возникнет ошибка.
Проверку на то, что аргументы переданы стоит делать с помощью isset($_GET['arg']). Потому что если с формы эти поля не будут переданы (если их совсем убрать с формы), то при сравнении $_GET['arg'] === '' возникнет ошибка.
Кстати, если передать 0, то будет ошибка, так как 0 считается за empty(это к вопросу в ДЗ)
Верно. Это тоже надо проверять с помощью isset.
v2
Результат isset нельзя сравнивать с null. Код проверки в самом начале нерабочий. Исправьте.
Проверка
не имеет смысла после того как вы уже использовали ключи этого массива. Она должна быть в самом начале.
Здесь в качестве ключа массива должна быть строка. Строки оформляются в кавычках. У вас же это - неопределенная константа.
Так правильно?
Теперь супер =)
У меня вопрос такой. После перезагрузки браузера перестал работать код. До этого работал. И другие варианты кода в коментах тоже не работают. В чем может быть причина?
Возможно, кеш. Ctrl + shift + R в браузере.
Ок. Только блоки кода if-else всегда должны быть в фигурных скобках.
1)
2)
3)
4)
5) Он прекрасен) Если улучшать то JS наверно.
Остальное отлично.
Не приходит в голову, как код можно нарушить, какие недостатки у кода и как его улучшить. Опыта еще не хватает.
Отлично :)
По улучшениям:
Проверку на то, что аргументы переданы стоит делать с помощью isset($_GET['arg']). Потому что если с формы эти поля не будут переданы (если их совсем убрать с формы), то при сравнении $_GET['arg'] === '' возникнет ошибка.
Делить ноль на что угодно - можно. Это корректное поведение и результатом будет 0. Калькулятор не показывает ошибки при такой операции, нужно просто вывести 0 в результате. То же и с умножением.
Делить что угодно на ноль - будет неопределенность (в пределе - бесконечность). И тут уже нужно показывать ошибку.
По 1 пункту задания: если использовать код
то при передачи 0 в качестве одного из аргументов результат будет "Не переданы аргументы", потому что 0 принимается как пустое значение.
Доработка калькулятора:
Проверку на то, что аргументы переданы стоит делать с помощью isset($_GET['arg']). Потому что если с формы эти поля не будут переданы (если их совсем убрать с формы), то возникнет ошибка.
Я поменял
на
и теперь если я не завожу какой-нибудь из аргументов, то мне возвращается "Ошибка! Введите число!" хотя по моим расчетам должно вернуться "Ошибка! Аргумент 1 или аргумент 2 не передан!". Сижу и пока что не могу понять почему так.
Вообще-то ошибка будет здесь:
Попробуйте удалить одно из полей на форме (не отправить пустым, а именно удалить инпут) и отправить запрос.
Удалил инпут, отправил запрос без аргумента и вот тут мне вернулось "Ошибка! Аргумент 1 или аргумент 2 не передан!", но потом вернув обратно опять тоже самое.
Почему здесь ошибка?
Потому что если на форме нет инпута с именем x1, то этого значения не будет в массиве $_GET. А если обратиться к несуществующему элементу, то будет ошибка.
А как передать значение если мы используем checkbox или radio
У них есть value, которое также доступно, как и значения инпутов.
Из улучшений: можно добавить обработку ',' для дробных чисел.
Супер! Отличная домашка
неправильно. Делить ноль на что-то можно.
По второму пункту ничего не исправили. Где проверка на то, что такие ключи в массиве вообще есть? Если с формы убрать сейчас input x1, и отправить запрос, то на строке
возникнет ошибка. Из-за того что нет в массиве такого ключа.
Чтобы этого избежать нужно проверять это с помощью isset, empty или array_key_exists. ОБЯЗАТЕЛЬНО!
Код:
Если передать в качестве аргументов передать 0 и 0, то выведется сообщение "Не переданы аргументы". А должно быть "На ноль делить нельзя".
Всегда используйте фигурные скобки для конструкций if-else, даже если одна строка. Правильно:
В остальном норм.
Понял, спасибо, всё исправил как надо.
Сначала нужно проверить, что x1 и x2 вообще есть в запросе. Это делается с помощью функции isset.
Зря убрали проверку. Запрос на бэкенд может прийти не только с вашей формы. И тогда всё пропало. Проверка обязательна! И на то, что в массиве $_GET есть ключи x1 и x2, и на то, что есть operation.
Также нет проверки на то, что x1 и x2 - числа.
Сделал всё, кроме 0. Я думаю, что 0 не воспринимается как число, т.к. трактуется интерпретатором как 'false', но ничего не смог сделать. Подскажите мою ошибку
А вот это что такое?
Для проверки числовых полей нужно использовать комбинацию из isset и is_number. Обязательно изучите и сделайте.
Так будет вернее?
Это вообще нерабочий код
Добавил возведение в степень, на больше не хватило фантазии, в таком исполнении калькулятора=)
Если такого ключа в массиве нет, то будет ошибка. Обязательно проверять сначала с помощью empty или isset. В вашем случае второй вариант.
ок, спасибо понял
Ужас с проверками! Вам нужно разобраться с тем, как работает empty и isset. Сейчас полный бред. Разбирайтесь, исправляйте.
Это что такое?
За исключением случая, когда x1 и x2 не переданы. Предварительно нужно ОБЯЗАТЕЛЬНО проверить аргументы с помощью isset.
если я ничего не передаю проверка отрабатывает и выводит return 'переданые аргументы не коректны';
При этом будет notice, так как данных ключей в массиве нет. Под "ничего не передаю" нужно понимать вообще отсутствие этих полей на форме.
не совсем понял is_numeric отсекает все те некорректные значения которые отсекает isset плюс отсекает строки зачем еще проверять isset-ом?
данных ключей в массиве нет - вы имели в виду вообще отсутсвие ключей в массиве или то что у этих ключей отсутствует значение? эти ключи в массиве есть но с пустыми значениями
Я имел в виду полное отсутствие ключей. Как если эти поля вообще убрать с формы, а затем отправить запрос. Поверьте, на реальном сайте найдутся пользователи, которые именно так и сделают.
я вас понял
Вопросы:
1)Правильно ли я понял, что GET и POST преобразует все в строки?
2)Когда я заполняю форму то на странице результата я вижу такую ссылку http://calculate.loc/result.php?numOne=3&index=%2B&numTwo=4
а если убрать все данные и ввести вот так http://calculate.loc/result.php, мне выдаст кучу ошибок, ведь форму получается просто проигнорили)
Это норм или мой любимый калькулятор смогут взломать как картонную коробочку?)
3)Почему в условии if вы пишите return a не echo? И как вообще return выводит строки, когда он только должен возвращать?))
Домашнее задание
Чтобы калькулятор принимал только числа, я на страницу с html формой поменял атрибут на type="number";
Валидация на форме это хорошо, но обязательно надо проверять запрос на стороне бэкенда. Для проверки стоило использовать функцию is_numeric. В остальном все хорошо.
(empty($_GET['x1'] != ' ') оператор empty используется не так.
А сейчас?
Ок
А как быть, если я хочу воспользоваться методом GET, а не POST. И пытаюсь сделать форму, в которую можно будет записать числа и получить результат на той же страничке? При таком написании все результаты равны нулю. Что я делаю не правильно?
Дебажить пробовал?
$x2 !='0' - при нестрогом сравнении можно опустить кавычки. А вообще здесь лучше в самом начале привести операнды к типу float.
В остальном - супер.
Функция empty() возвращает true, когда переменная не существует и имеет пустое или нулевое значение. Поэтому в данном примере следует использовать проверку только на null (Например функция is_null()).
При делении на 0 вызывается Warning: Division by zero. Следует отлавливать передачу "0" второму аргументу, когда выбрана операция деления.
При передаче в качестве аргумента строки будет выводится Warning: A non-numeric value при выполнении арифметических выражений. Чтобы отловить передачу нечисловой строки можно воспользоваться функцией is_numeric().
5.
Улучшить.. Хорошо бы проверку на корректность ввода добавить еще на стороне клиента, дабы не обращаться к серверу, если пользователь накосячил. При этом проверку на серве тоже следует оставить на тот случай, если проверка в клиентской части косячная.
Еще можно использовать функцию number_format($result, 2), чтобы задать точность и избежать проблем при выполнении операций с дробными числами. Чтобы 36-35.99 равнялось 0.01, а не 0.009999999999998 :D
Супер!
С вводом ноля и чисел разобрался, деление и умножение добавил, а вот как ещё сломать не придумал(
Если x1 или x2 не придут в запросе, то будет ошибка. Обязательно нужно это проверить.
Сколько не пробовал выдаёт, что не переданы аргументы, а не ошибку. Как сделать чтобы они не пришли и увидеть ошибку?
isset
Всё равно не понял, зачем использовать isset? Ведь у меня и так выдаётся сообщение, что не переданы аргументы, а не ошибка.
Они могут не придти, если их убрать на форме. Это может сделать любой посетитель сайта. Более того, он может сделать форму хоть прямо у себя на компе и отправлять запрос на ваш сервис. А сервис будет тонуть в ошибках.
Добавил isset, но у меня и без него выводилось сообщение о непереданных аргументах, специально убирал одно поле в форме ввода для проверки.
Значит у вас выключен показ ошибок.
Спасибо за разъяснения, хочется понимать, а не просто за вами копировать.
При отсутствии указания метода выбирается "Get" ?
Гуглить пробовал?)
Добрый день,такое решение задачи неверно? (пункт про ввод только цифр)
Обязательно нужно проверять данные на бэкенде (на PHP, в нашем случае). Форму пользователь может изменить прямо у себя в браузере.
Куда делись проверки empty/isset?
Пришлось немного подсмотреть. Хочется, конечно, всё самостоятельно делать. И всё же очень крутые уроки, прям очень!!!) Спасибо большое!
В каком случае это возможно?
Да, какой-то шлак. Даже объяснить не могу, зачем сделал это. Сейчас проверил и понял, что не работает. Когда ввожу ноль в форму не видит этот аргумент, и не по причине этого условия. Я попытался использовать несколько вариантов с нулём(пробовал в условии null, пробовал в условии 0, пробовал функцию isset для проверки на отличие от null) и результат не меняется: всегда игнорит ноль. Если убрать второе условие, ноль всё равно не видит, а операцию деления на ноль выполняет. Магия прям. Пытался разобраться чем отличается ноль и null, понял только, что разница в том, что 0 - число, null - переменная без значения, и всё же вопрос почему в строке не определена переменная не разрешился. Короче, HELP!
null - это отсутствие какого-либо значения. 0 - это числовое значение.
isset(0) вернёт true. В то же время isset отлично подходит для проверки того, есть ли ключ в массиве - isset($array['some_key']). Для нашего случая подходит, в отличие от empty, который вернёт true, как для null, так и для 0, так и для пустой строки.
Попробовал ещё один вариант, вроде работает нормально.
Если с формы убрать поля x1 и x2, то скрипт будет падать с ошибкой. Такого допускать нельзя. Нужно обязательно проверить на бекенде, что данные пришли.
Дубль 3. Проверки на бекенде нужно делать железно и для этого мы и используем функции is_numeric и isset(в данном случае) и если что-нибудь поменяется во фронте, эти функции отработают, так? Я попробовал убрать в input-ах имена переменных и в случае без isset возвращает вариант с is_numeric. После добавления isset, возвращает вариант с ним, стало быть проверяет, что данные есть. Результат не считает(вероятно потому, что убрав имена из полей мы прописанную логику нарушили) но и ошибку не выдаёт: так и должно быть? Ещё я попробовал после возвращения имен в полях закомментировать isset и ноль как число работает. Вероятно из-за того, что я убрал проверки с empty, ноль теперь работает, даже если закомментировать всё, кроме ['operation']. Когда делал задание используя empty, бился долго и не знал, что и 0, и пустую строку, и null, empty возвращает со значением true. Читал доку и как-то невнимательно, видать. После Ваших замечаний понял, почитал доку ещё - закрепил. Простите, что так много текста, просто пытаюсь разобраться, чтоб дальше не тормозить. Такое решение нормальное?
И снова будет ошибка. Просто убери поля из формы и отправь запрос. Он должен корректно обработаться.
Ошибку не выдаёт. Может у меня что-то не подключено? Хотя по предыдущим урокам всё как по маслу шло, только я тупил) Видать, что-то не то делаю или не понимаю что сделать. Если я уберу поля из формы(HTML), то как введу данные?) или речь о полях с пустыми строками в условиях?
Речь о том, что данные и не надо вводить. Представь, что пользователь взял и изменил форму и удалил поля. Прямо в браузере это можно сделать. А потом взял и отправил кривой запрос, просто чтобы поломать скрипт. Поля вообще не придут в запросе и когда ты напишешь
то тут возникнет ошибка, так как такого ключа в массиве попросту нет. Если ошибки не видишь, значит их вывод у тебя выключен и нужно их включить в php.ini.
error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT
display_errors = On
display_startup_errors = On
log_errors = On
Ведь так должно быть? Это я скопировал из своего php.ini. Погуглил, вроде похоже) Везде практически одинаковые советы. И ошибки при этом не выдает. Мне нужно использовать проверку на то, что GET вообще пуст?
Оспаде, я запутался.
Нотисы тоже нужно включить. Почитай пожалуйста сам про это всё. И не забудь перезапустить OpenServer после изменений в php.ini
Здравствуйте, подскажите в чём причина такой проблемы?
В файле index.php такой код:
И с ним выдаёт ошибку 404. Если сменить путь на просто <form action="result.php">, то всё работает, НО не почему-то в файле result.php работает только
и если сменить на $result = require DIR . 'calc.php';, то выдаст ошибку:
Страница недоступнаСайт localhost пока не может обработать этот запрос.
HTTP ERROR 500
Все файлы находятся в 1ой директории, в одной папке
Путь из атрибута action формы используется браузером, это то, что в адресной строке. А то что через require - это путь на сервере. Это абсолютно разные вещи!
Ты index.php в браузере по какому адресу открываешь?
По стандарту на alt + f2 : http://localhost:63323/learning/index.php?_ijt=v5qtoapu22i2bfpjbe8n1g0br9
А OpenServer не настраивал?
К сожалению, нет. Занимаюсь на работе, на рабочем пк ( да, звучит странно) тут стоит iis express. На днях собираюсь брать ноут для себя, и вот тогда уже поставлю open server)
Ставьте. Это вообще не дело)
Хотелось бы добавить, что условие
Не может выполниться, тк у нас всегда по умолчанию стоит знак "+", поэтому изменил в форме 1ый атрибут option и поставил:
Для блоков if-else всегда используйте фигурные скобки. В остальном все хорошо.
Принял, спасибо) Ох и повозился я с тем, чтобы при пустой строке в инпутах при помощи isset не было результата типа "пустая строка + 1 = 1")
Если не передать x1 или x2 (полностью убрав поля с формы), то будут ошибки.
исправил
Теперь если передать 0, то будет писать что аргументы не переданы. Прочитай в документации про isset.
если оставить проверку is_numeric все корректно отрабатывает и если даже нет инпутов ошибки нет
Ты инпуты вообще удалил с формы, и нет ошибок? Значит они выключены и их надо включить в php.ini. Потому что происходит обращение к элементу массива по несуществующему ключу. А это ошибка уровня Notice.
Нужно проверить что x1 и x2 пришли в запросе.
Вот так?
Теперь если передать 0, то будет писать что аргументы не переданы. Прочитай в документации про isset.
Нужно сначала проверить что x1 и x2 пришли в запросе. Если их убрать с формы и отправить запрос, это должно корректно обработаться. А сейчас возникнет ошибка. Смотрите в сторону empty/isset.
И ещё нет проверки на то, что это числа.
Добрый вечер! и снова я с вами проверьте дз пож?
Полная ерунда, изучите как работает empty и isset. Почитайте официальную документацию.
Прочитайте документацию по isset и empty. Много логики ненужной.
Сперва полез в index.php сменить тип с text на number, но понял что это не то. Т.к. дробные числа не получиться написать.
Кстати, а есть ли необходимость в первых двух условиях, если и так все условия обработаны?
Вы вот здесь уже задали переменные x1 и x2. Зачем используете дальше по коду значения из $_GET? А потом опять присваиваете значения.
О каких условиях вы спрашивали?
Об этих. Поправил код.
Ну, первое конечно можно убрать, но тогда сообщение не будет полностью описывать проблему.
Ну а без проверки операции на пустоту программа и вовсе выдаст ошибку на строке
если не будет передана операция.
Так что, обе строки нужны.
Не даст передать нули в качестве аргументов!
Имена функций пишутся с маленькой буквы! Для чего эта функция? Тут мы должны принимать на вход число. Для чего там кодирование html тегов?!
Переделайте.
Где проверки на то, что значения были переданы? Если с формы убрать инпуты и отправить запрос, то будут ошибки.
Если убрать с формы x1 и отправить запрос, то снова будет ошибка. Проверки на наличие ключа в массиве снова нет.
Правильно ли я понимаю, что при ф-и риквае, файл1 который вшиваю в файл2, имеет доступ к переменным файл2?
То есть в файле2 пишем риквае файл1
А код слабо написать?) Риквае какие-то)
Ответ на вопрос - да.
Где проверка на то что x1 и x2 вообще переданы?
Если передать в х1 или х2 ноль, то будет писать, что не переданы аргументы.
Вот что получилось!
ПО 5 заданию затрудняюсь ответить.
Вместо этого используйте isset, с дальнейшей проверкой is_numeric. А то так дважды приходится is_numeric вызывать.
Почему одно приводите, а другое нет? И почему к целому числу, а не к float? И почему не через (int)$value, как было в предыдущих уроках?
в чем разница isset и empty
empty на мой взгляд более универсальна из - за проверок на null 0 '' и тп.?
Отлично.
В вашем вопросе уже есть ответ. Нам не нужна проверка на 0.
1) Функция empty получила значение '0', а данное значение для нее является пустым, поэтому выдало сообщение 'Введите числа'. Поменял функцию empty на isset
2) Сделал. Добавил в два input'a в index.php и два case в calc.php
3) Вышла ошибка warning о делении на ноль. Добавил дополнительное условие
4) Вышла ошибка warning обнаружено нечисловое значение. Изменил тип для input'a, с text на number и добавил атрибут step="any", чтобы считать числа float
5) a) В option у нас нет пустого значения, поэтому условие operation можно убрать
b) В файле calc.php можно вначале добавить переменные для x1, x2 и operation, чтобы код легче читался
c) Из switch убрать default, т.к. операция будет выбрана в любом случае
d) Можно добавить еще операторы для вычислений
Сначала обратились к элементам массива, затем проверили их существование. Это грубая ошибка, которая приведет к ошибкам кода. Если убрать с формы x1 и x2 и отправить запрос, то всё рухнет в ошибках.
isset не проверяет, являются ли переданные значения числами. Если передать буквы, опять же будет ошибка.
Этого недостаточно. Любой злодей может изменить форму как ему угодно, прямо у себя в браузере. Нужно всегда валидировать значения на бекенде.
И снова можно изменить форму через инструменты разработчика/создать новую у себя локально и отправлять запросы, ломающие скрипт. Ни к чему хорошему это не приведет.
И снова нет, по той же причине.
Не пойму, почему операция "число" поделить на "не целое число" (например 1 / 0.2) приводит к "Операция не поддерживается"?
А если не передан только один аргумент? Это разве ок?
А если передать два нуля, разве ничто не передано?
if (empty($_GET['x1']) || empty($_GET['x2'])) {
return 'Не переданы аргументы';
Так ?
А если два нуля страха, вроде как, нет. На 0 деление защищено. А остальные операции выдадут 0. Или я не прав ?
Уже лучше, только теперь другая ошибка на этой же строке. Если мы передадим в качестве аргументов нули, то программа на этом месте остановится и скажет "Не переданы аргументы". Хотя это абсолютно нормальные аргументы, являющиеся числами. Калькулятор позволяет складывать нули.
if (!isset($_GET['x1']) || !isset($_GET['x2'])) {
return 'Не переданы аргументы';
Как вариант =) ?
Да, теперь отлично
Не сильно перекрутил с if'ами?
Для чего здесь приведение к float?
Вообще всё можно сделать гораздо проще. Изучите конструкции isset и is_numeric. Жду вашего отдельного комментария с упрощенным вариантом.
Так лучше?
Всё отлично, кроме
Нужно писать так, чтобы пользователю было понятно, что не так.
Понял. Изменил на 'Делить на ноль нельзя'.
Ещё вопрос по поводу isset, он смотрит конкретно на то что бы в х1 и х2 было наполнение или в целом на существование такой детали массива?
Что мешает прочесть документацию? =)
А я прочел, даже много раз, до меня просто долго доходило))
У меня такое бывает, но сейчас уже разобрался что к чему, спасибо.
Как я понял isset проверяет существование переменной, либо ключа в массиве, но не обращает внимание на присутствие "содержимого" и в случаях с:
$hello = 'привет';
или
$hi='';
В обоих случаях isset вернет true
Верно?
'' - это пустая строка. Отсутствие значения - это null. И вот на нём isset уже вернёт false. Не нужно использовать термин "содержимое". Используйте термин "значение".
А если не переданы значения? Типа ок? На следующей же строке после закрывающей скобки блока этого условия произойдет ошибка.
Так как происходит обращение к несуществующему ключу.
Ну ёлки-палки! Ну где вы увидели, чтобы писали конструкции if-else без фигурных скобок? Пишите их всегда, придерживайтесь того же стиля, что и в моих уроках. Рано вам было это говорить, но раз уж копируете код не пойми откуда, то ознакомьтесь со стандартами PSR. И всегда следуйте им при оформлении. Я в своих уроках их всегда придерживаюсь, откуда вы умудряетесь хватать такие ужасные примеры?
В остальном по логике теперь всё ок
Я в очередной раз не понимаю о чем речь. С чего Вы взяли, что я откуда-то что-то копировал. а не сам писал??
ОК
Уточните, в чем ужас, чтобы я понимал себе на будущее. Вы про отсутствие фигурных скобок и о том, что не учтен вариант отсутствия переменных?
Да) Возможно, вы до этого изучали другие языки, или смотрели устаревшие материалы по PHP. Но пожалуйста, старайтесь придерживаться такого же стиля, что я даю в своих уроках. Он на данный момент актуален.
Супер!
Подскажи пожалуйста, как сделать, чтоб результат отображался на этой же странице, где сама форма в index.php?
Т.е. ставим перед кнопкой Посчитать знак "=" и выводим результат тут же, при клике на кнопку Посчитать.
Я попробовал просто в index.php сделать подключение:
и в нужном месте вывести:
Но потом меня сбило с толку, что делать с form action="" что тут писать тогда?!
Правильно ли вообще я думаю? В данном случае после подключения файла выводится ошибка:
https://cloud.mail.ru/public/EL5G/U99mFpcYx
и в результат сразу выводит информацию, даже не кликнув по кнопке Посчитать
В form action пишется адрес, на который нужно отправить запрос. В вашем случае это index.php
Хорошо, а по поводу остального?
А что вам ещё непонятно?) Рассказывайте
В данном случае после подключения файла выводится ошибка:
https://cloud.mail.ru/public/EL5G/U99mFpcYx
и в результат сразу выводит информацию, даже не кликнув по кнопке Посчитать. Как это исправить?
Нужно проверять что необходимые данные пришли в запросе, и только потом подключать файл, как вариант. В ошибке же всё написано. Нужно обрабатывать запрос.
Проверку сделал:
Теперь ругается на:
в файле index.php
Вот скриншот: https://prnt.sc/r17mua
Не пойму, что теперь делать?
Эта переменная объявляется только если пришел запрос с query-параметрами, а ты ее используешь всегда, даже когда запрос без параметров. О чем в ошибке и написано.
как решить проблему?
Либо объявлять переменную всегда, либо не использовать её, если она не объявлена.
Если аргументы не передать, то уже здесь возникнет ошибка. Попробуйте убрать инпуты для них с формы и отправить запрос.
добрый день, сам сделал только 1 и 2, третье подсмотрел, всё как у всех, так что флудить не буду. Ломал голову пару вечеров по поводу третьего, но прежде чем писать код на 10 стр. решил подглядеть, оказалось, что всего то одна строка как тут case '/' :
$result = $x2 != 0 ? ($x1 / $x2) : 'На ноль делить нельзя';
break;
Ок
Над другими заданиями пока размышляю)
Ну обработку деления на 0 уж надо бы добавить, не?)
Перестаньте уже писать закрывающий тег.
Почему в итоге выводите как $result если поделили на 0? Это ведь ошибка, значит нужно сразу сделать return, а у вас программа продолжает выполняться как ни в чем не бывало. И повторюсь еще раз - не нужно в одну и ту же переменную складывать разные типы данных. $result - для числа, а вы туда текст ошибки пихаете.
Ну нее, так не годится. Сначала нужно проверить, что такие ключи в массиве вообще существуют, иначе можно нарваться на ошибки.
Сначала нужно убедиться, что эти ключи вообще в массиве есть. Иначе тут будет ошибка, если в запросе эти поля не придут.
Достаточно будет только второй проверки, она покрывает оба кейса. Контекста нет - нужно явно писать, что пошло не так.
Это невозможно, если до сюда дошли, то оба аргумента numeric, а значит уже не могут быть пустыми строками.
0 / true - ерунда полная
Закрывающий тег не нужен! Сколько раз повторять)
Повторюсь:
Сначала нужно убедиться, что эти ключи вообще в массиве есть. Иначе тут будет ошибка, если в запросе эти поля не придут.
Всё, исправил код...
Ошибка здесь, в самой первой строке. Ничего не исправили.
Вот так?
Например да. Но конкретно по вашему коду достаточно выше этих строк вынести проверку с использованием array_key_exists. Жаль, что самостоятельно не получилось у вас к этому придти. Поправьте и пришлите исправленный вариант.
В принципе всё работает :/
Для строк используются одинарные кавычки.
По-хорошему нужно еще проверять, что в запросе пришёл корректный operation.
Хех на счёт "0 / true" соглашусь, я написал полную дичь :D
Можно добавить возведение в степень и прочие более сложные операции.
Можно нарисовать кнопки, чтобы в них можно было тыкать, вместо того, чтобы вводить инпуты (ну, мало ли, у человека только мышь есть)
Сломать можно, думаю, слишком длинным вводом
Отлично.
Закрывающий тег в конце файла только не надо ставить.
Здравствуйте, форма передаёт GET запрос в result.php, почему вам удалось получить все аргументы GET запроса из другого файла(вызывая $_GET в calc.php), почему не возникло ошибки?
Пыталась с помощью strpos проверить есть ли "," в строке.
strpos(',7', ',') != false будет false
strpos('0,7', ',') != false будет true
Почему так происходит?
Сначала нужно проверить, что в массиве вообще есть такой ключ. Иначе будет ошибка
Да и вообще непонятно для чего тут пробелы обрезать, если должна быть проверка на числа. Она их и так не пропустит.
А теперь?
Если параметр не придет с формы, по-прежнему будет ошибка.
Можно подробнее, какая ошибка? Сейчас если поле пустое, то выводится сообщение:
"Не переданы аргументы". Если 0, то считает.
Если убрать полностью поле x1 с формы и отправить запрос, то в массиве $_GET просто не будет ключа x1.
Далее произойдёт следующее - empty($_GET['x1']) вернёт true, так как за ним следует логический оператор &&, интерпретатор пойдет вычисляет значение справа от этого оператора и вот здесь:
Произойдёт ошибка, потому что вы обратились по несуществующему ключу.
Сначала нужно удостовериться, что вообще ключ в массиве есть. Это можно сделать либо с помощью isset, либо с помощью array_key_exists.
Спасибо за объяснение. А теперь верно?
Какие ключи? Нужно больше деталей.
А для operation выше уже проверили с помощью isset.
Для чего эта проверка, если ниже проверим на то, что это числа.
Для строк используются одинарные кавычки. Зачем использовать функцию не по назначению? Для поиска символов используйте strpos. Сравнивать при этом нужно строго, то есть с !== а не !=, чтобы избежать приведения нуля к false.
У нас же был урок по приведению данных:
Комментарии здесь ни к чему, и так всё понятно.
Сначала нужно проверить, что в массиве вообще есть такой ключ. Иначе будет ошибка.
Да и вообще непонятно для чего тут теги обрезать, если должна быть проверка на числа. Она их и так не пропустит.
Такой вот вопрос: В чем разница между проверкой на ввод числа на фронте и бэке ? Лучше ставить type="number" в инпуте, или всё же проверять с помощью php?
Ну ага, сначала обратились к потенциально несуществующим ключам массива, а потом проверили его на пустоту. В итоге если поле из формы убрать и отправить запрос, то можно утонуть в ошибках.
Я вот сделал так и решительно не понимаю, что можно улучшить, кроме уж совсем совершенствования калькулятора для подсчета, например, длинного выражения, но такое я пока не умею делать(
Если аргументы вообще не передать (удалить их с формы и отправить такой запрос), то будет ошибка, потому что таких ключей в массиве не будет.
Заменить:
на:
добавить:
на:
и
на:
и
атрибут pattern с выражением "^[0-9]+$" разрешает отправлять форме только числа.
5.Можно добавить операции, например возведение в степень.
Я бы изменил:
на:
для того, чтобы было понятно какая операция не выполняется.
Если аргументы вообще не передать (удалить их с формы и отправить такой запрос), то будет ошибка, потому что таких ключей в массиве не будет.
Тогда уж return, по аналогии с другими ошибками.
Валидация на фронте не спасет, я могу прямо в браузере ее поменять как хочу, в консоли разработчика. Нужно проверять, что это число именно на бэке, и делать это всегда.
Опасно выводить вот так любые данные, прилетевшие с фронта, там может быть вредоносный XSS-код
заменил на:
я не придумал пока что другого варианта,
тут же учёл проверку "Является ли аргумент числом".
изменил на:
исправил на:
спасибо.
Еще раз повторюсь. Если аргументы вообще не передать (удалить их с формы и отправить такой запрос), то будет ошибка, потому что таких ключей в массиве не будет. Нельзя брать и обращаться к ключам массива, пока не убедились, что они там есть. Пока это не исправите дальше даже смотреть не буду.
Спасибо за подсказку.
Вроде я нашел:
проверил работу при удалении аргумента(ов) из формы
Красава! :) Совсем другое дело
Спасибо!
Какая красота! Идеальная домашка с первого раза!
Пройдите дополнительный урок Обработка форм в PHP и исправьте ошибки
выполнилось, потому что функция empty($_GET['x1'] вернула TRUE, а функция empty(): Возвращает FALSE, если переменная существует и содержит непустое ненулевое значение. В противном случае возвращает TRUE. Мы передали в нее 0, соответственно она вернула TRUE.
Исправить можно так:
2.
Доработка:
4.
Пройдите дополнительный урок Обработка форм в PHP и исправьте ошибки
Пройдите дополнительный урок Обработка форм в PHP и исправьте ошибки
А чего приведение сразу не добавили?) Но в целом всё ок, работать будет без ошибок.
Имеется в виду приведение к float?
Ага
Мой пример. Из проблем заметил, что не воспринимает запятую, только десятичную точку при вводе аргументов типа float.
and нужно заменить на &&
Пройдите дополнительный урок Обработка форм в PHP и исправьте ошибки
Учитывая дополнительный урок, получилось так:
Для чего написали ?? null после filter_input?
После Вашого вопроса задумался и понял, что это лишнее. Если в filter_input подать строку, то переменной присвоит значение null. А это неправильно. Я правильно понял свою ошибку?
Дело в том, что вы проверяете с помощью null-coalesce оператора что там null и присваиваете... null! Бесполезное действие получается.
Теперь понял. Спасибо за ответ. Если убрать null-coalesce оператор, то остальное правильно?
Да, но лучше исправляйте и потом уже спрашивайте, потому что иногда выходит так что говорим вроде бы об одном с учениками, а они имеют в виду совсем другое
Самостоятельно получилось выполнить где-то только 50%, пришлось прибегнуть к помощи комментов.
Урок очень понравился. Из усовершенствований хотелось бы чтоб дробные числа вводились через "," как в стандартном калькуляторе.
Отлично. Еще советую дополнительно изучить дополнительный урок Обработка форм в PHP
Отличная, образцовая домашка!
Сам смог добавить умножение и деление. При возведении в степень в результате появлялся пустой квадратик. Поэтому не стал добавлять. Урок понравился очень. Форматирую с Ctrl+Alt+L. Я просто делаю copy-paste своего кода в комменты. Может из-за этого нарушается форматирование?
В этой домашке всё хорошо с форматированием
Пройдите дополнительный урок Обработка форм в PHP и исправьте ошибки
Тяжело дается тема, много нового
Супер!
Предыдущие задачи решены, есть в комментах, теперь новые:
https://codingzone.io/problems/9/solution/825
https://codingzone.io/problems/10/solution/842
Интересный ход мыслей для второй задачи) Я решал так https://codingzone.io/ru/problems/10/solution/594
Если передать 0, то пишет, что не переданы аргументы. Это происходит потому, что функцией empty cледующие значения воспринимаются как пустые:
"" (пустая строка), 0 (целое число), 0.0 (число с плавающей точкой), "0" (строка), NULL, FALSE, array() (пустой массив)(цитата из официальной документации). Решил проблему конструкцией !isset, предварительно почитав комменты :) Если поделить на ноль, то "результат вычислений:
10 / 0 = INF". Исправил. Если добавить строку, калькулятор не работает корректно. Исправил.
https://codingzone.io/problems/9/solution/980
https://codingzone.io/problems/10/solution/981
Отлично!
При передаче 0 функция empty воспринимает его как пустое значение, поэтому (уже после того как прочитал комменты и дополнительный урок) добавил isset.
При делении на ноль, то выводится 3 / 0 = INF, добавил для этого условие if
При вводе строки калькулятор работает не совсем корректно, добавил для этого условие if с функцией is_numeric
В качестве улучшения можно добавить распознавание запятой в десятичных дробях или добавление кнопок вместо самостоятельного ввода, больше никаких улучшений не надумал.
Доп. задание 1 -https://codingzone.io/ru/problems/9/solution/1624 или так https://codingzone.io/ru/problems/9/solution/1627 (не знаю, какой вариант лучше)
Доп. задание 2 - https://codingzone.io/ru/problems/10/solution/1630
Возник так же вопрос - какую литературу стоит читать касательно PHP и стоит ли вообще? Просто слышал такое мнение от людей, которые себя программистами называли, что читать по программированию ничего не стоит и чуть ли не бесполезно
Некорректно сравнивать массив с пустой строкой.
В остальном ок.
По codingzone сравниваете с тем, что даётся по кнопке show our solution
По поводу литературы - этих курсов будет достаточно для начала, вряд ли в книгах будет что-то нужное и при этом этого не будет на phpzone
Исправил, вместо сравнения использовал empty.
Да, в codingzone я увидел образцовое решение, просто не могу понять, стоит ли писать такой код, который только из встроенных функций и состоит или лучше все-таки какую-то часть писать самому, не полагаясь на функции.
Весь смысл в написании алгоритма самостоятельно, за исключением функций для преобразования ввода и вывода.
1 задача
https://codingzone.io/problems/9/solution/1745
2 задача
https://codingzone.io/problems/10/solution/1747
Норм!
Что можно улучшить, не знаю. Может сделать вывод результата на той же страничке, где вводим числа? Чтоб при нажатии кнопки "посчитать" справа выводился ответ?
Пройдите дополнительный урок Обработка форм в PHP и исправьте ошибки
Пройдите дополнительный урок Обработка форм в PHP и исправьте ошибки
Привет, решение задачи
Привет. Это просто ссылка на задачу. Если все тесты прошли - мне нет смысла смотреть) Если не прошли и непонятно почему - готов помочь
Тесты прошла, задачи решила!
Супер!
Привет, вот что получилось.
Нельзя передать 0 в качестве аргументов.
Привет, прочитав комментарии, исправила свою ошибку.
calc.php
А как теперь высылать ссылки на решения с задач? Или уже этого не нужно? Я смотрю вы уже codingzone под свой домен перенесли...
Пройдите дополнительный урок Обработка форм в PHP и исправьте ошибки.
А зачем? Если тесты прошли, значит всё ок, к тому же там есть сразу моё решение, с которым вы можете свериться.
Ок, спасибо! В том уроке и ответил
это так не работает. Изучите детально эти конструкции и перепишите правильно.
Всегда используйте фигурные скобки для блоков if-else.
эта проверка не имеет смысла, так как выше мы уже проверили:
Пройдите дополнительный урок Обработка форм в PHP и исправьте ошибки
У меня почему то
При пустых формах всё равно возвращает 1.
Ну запрос-то от этого не пустой) Пустые строки передаются из полей.
А, понял - при клике "Посчитать" я попадаю не на адрес:
http://myproject.loc/result.php
который возвращает строку 'Ничего не передано!',
а на адрес:
http://myproject.loc/result.php?x1=&operation=%2B&x2=
который возвращает 1.
Значит не здесь возвращается. Посмотрите дебаггером, на какой строке происходит возврат. Здесь 1 никак не может вернуться
Пройдите дополнительный урок Обработка форм в PHP и исправьте ошибки
Не нужно скидывать код, если прошли все тесты. Если же тесты не прошли и вам что-то непонятно - задавайте вопрос)
Код файла Calc:
Пройдите дополнительный урок Обработка форм в PHP и исправьте ошибки
Пройдите дополнительный урок Обработка форм в PHP и исправьте ошибки
Добрый день, я прошла указанный урок. Но не понимаю, где у меня допущены ошибки. Если не брать во внимание упрощение через filter_input и приведение к типу float, то основной обсуждаемой ошибкой в уроке было игнорирование isset. Но у меня он учтен. Поэтому могу попросить точно ткнуть пальцем, что тут не так?)
Прошу прощения. Действительно, всё в порядке
Проблема - нельзя задать аргументы, равные нулю.
Пройдите дополнительный урок Обработка форм в PHP и исправьте ошибки
Теперь отлично
Получается вот так? Но написанное мной тоже работало, или это не совсем корректно написано?
is_null не используется сейчас. вы проверили, с прошлым вариантом пустой POST-запрос не приводил к ошибкам?
Пройдите дополнительный урок Обработка форм в PHP и исправьте ошибки
Вроде теперь все ок
А нужно ли делать дополнительно приведение после
?
Этот код только в качестве примера которым я проверял, будет ли работать или нет.
код выше выдал ошибку, потому что переменные не числа, поэтому я сделал приведение типов после проверки на число, но был еще такой вариант
и после уже сделать проверку на число на всякий пожарный.
Обработка форм в PHP читали?
Читал, но возможно что-то упустил. Опять я косячу?
Непонятно почему не смогли совладать с filter_input. В чем вопрос?