Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Проверка и отправка формы (jqery+php) (https://javascript.ru/forum/misc/78695-proverka-i-otpravka-formy-jqery-php.html)

joyandjoy 21.10.2019 21:02

Проверка и отправка формы (jqery+php)
 
Здравствуйте!
Целый день пыхтел, гуглел, совсем загудел :) Прошу помощи :help:

Есть форма комментариев, без родной капчи, пытаюсь ее прикрутить.У
Удивительно, но алгоритм такой: каптча дает "ок" - форма должна отправиться, каптча дает нет, должна появится ошибка.

Вот форма
<form method="post" name="uploader" enctype="multipart/form-data" id="commt">
    		<inline>
    			<div class="textarea"> 
    					<inline class="second">  
    						<input type="text" name="sended_name" required placeholder="Имя" value="<?echo$REAL_NAME?>" <?echo$disabled_name?> >	  
    						<label><img src="<?echo$dir_blocks_http?>email.png" alt="email" class="email"></label>
                            <input type="email" name="sended_email" required  placeholder="Email" value="<?echo$REAL_EMAIL?>" <?echo$disabled_email?> > 
                            <input type="hidden" name="img_hidden" required  placeholder="Email" value=""> 
							<input type="submit" id="submit" name="send_comments"  value="Отправить"/>				
  
							<span><?=$_SESSION['msg']?></span>
							<?php unset ($_SESSION['msg']);?>
										</inline>
							<p>Сколько <?=$color?> яблок?<br /><?="$first_l$second_l"?> <br />
							Ваш ответ: <input type="text" id="result" name="result" value="" style="width:17px; font-weight:bold;margin-top: 10px;" /><br /></p>
    			</div>              
    		</inline>


<script>
     $(document).ready(function(){
    $("#commt").submit(function(){return false;});
    $("#send_comments").on("click",function(){
        
    var msg=$("#result").val();


    // если обе проверки пройдены
    // сначала мы скрываем кнопку отправки
    $("#send_comments").replaceWith("<em>отправка...</em>");
	$.ajax({
	type:'POST',
	
	var resok = $('div.hidden').data('lat');
	
	resok:$("#commt").serialize(),
	success:function(resok){
	    if(resok=="1"){
		$("#commt").fadeOut("fast", function(){
		$(this).before("<p><strong>Ваше сообщение отправлено</strong></p>");
		setTimeout("$.fancybox.close()",1000);
	    });
	    }
	}
	});
    
    });
});
</script>

<?php
$first = rand(1, 5); //получаем случайное значение
$second = rand(1, 5);

if ($first == $second) {//убираем возможность одинаковости первого и второго числа и исключаем тем самым нулевой результат
 $first = rand(1, 3);
 $second = rand(4, 5);
 }

 function mirror ($name, $name_l) //привязываем к выводимой в браузер ($first_l и $second_l) переменной текстовое значение в соответствии с используемой при вычислении 
  {
$g = "1";//картинка яблока
$r = "0";
  switch ($name) { 
case 1:
    $name_l = "$g"; break;
    case 2:
    $name_l = "$r$g"; break;
case 3:
    $name_l = "$r$g$r"; break;
case 4:
    $name_l = "$r$g$r$g"; break;
case 5:
    $name_l = "$r$g$r$g$r"; break;
}
return $name_l;
 }
 
 $first_l = mirror ($first, $first_l); //инициализируем переменную
 $second_l = mirror ($second, $second_l);

// привязываем количество цвета к значению $first и $second 
 function mirrorColor ($numvar){
     switch ($numvar) {
        case 1:
        $green = 1;
        $red = 0; break;    
     case 2:
        $green = 1;
        $red = 1; break;
     case 3:
        $green = 1;
        $red = 2; break;
     case 4:
        $green = 2;
        $red = 2; break;
     case 5:
        $green = 2;
        $red = 3; break;
    }
 return array ($green, $red);
 }
 
$f_color = mirrorColor ($first);// инициализируем массив
$s_color = mirrorColor ($second); 

$gr_word = "<span style=color:green;font-weight:bolder>зеленых</span>";
$red_word = "<span style=color:red;font-weight:bolder>красных</span>";
 
$t = time();  //инициализируем переменную для смены операций временем в секундах на момент запроса
  
if ($t & 1) //меняем операцию в соответствии с четностью переменной
        {
           $_SESSION['res'] = $f_color['0'] + $s_color['0']; //заносим результат в сессионную переменную
		      $color = "$gr_word";//выводимое в браузер название цвета
         }
else
        {
          $_SESSION['res'] = $f_color['1'] + $s_color['1'];
		      $color = "$red_word";
        }
  

if (isset($_POST['result'])) { //если это был ответ


if (trim(strip_tags($_POST['result'])) == $_SESSION['res']) { //убираем, на всяки случай, теги и пробелы с обоих сторон и сравниваем результаты

$_SESSION['msg'] =  " Верно<br />";

 

$Lat = ["1"];

}
else {
$_SESSION['msg'] =  " Ошибка<br />";
$Lat = ["0"];
}
 
if (empty($_POST['result'])) {
$_SESSION['msg'] = " Нужно ввести ответ...<br />";
$Lat = ["0"];
}

 } 
 
  ?>

laimas 21.10.2019 21:19

Цитата:

Сообщение от joyandjoy
if (isset($_POST['result'])) { //если это был ответ

И где это проверяется, в том же файле, в котором до этого вот это?

$first = rand(1, 5); //получаем случайное значение
$second = rand(1, 5);
....

joyandjoy 21.10.2019 22:00

Цитата:

Сообщение от laimas (Сообщение 514357)
И где это проверяется, в том же файле, в котором до этого вот это?

$first = rand(1, 5); //получаем случайное значение
$second = rand(1, 5);
....

Один файл, порядок: недоphpобработчик - > форма -> jqeryнедоскрипт

laimas 21.10.2019 22:14

Если один файл, то это не верно, структура файла должна быть такой:

1) старт/продолжение сессии
2) проверка наличия запроса клиента и если он произошел, то проверяем условия каптчи и другие поля, результат проверки отдаем клиенту, после чего обязательное прекращение работы скрипта
3) подготовка параметров каптчи
4) вывод html страницы клиенту

$_SESSION['msg'] = " Верно<br />"; - это, как и <span><?=$_SESSION['msg']?></span><?php unset ($_SESSION['msg']);?> лишнее. Данный элемент должен выводить текст по умолчанию, а ответы на проверку совсем не нужно хранить в сессии, у вас асинхронный запрос. Поэтому проверили запрос, выдали перечень всех ошибок клиенту, если они есть, или дальнейшее действие, если все Ок.

"убираем, на всяки случай, теги и пробелы с обоих сторон и сравниваем результаты" - это бесполезность, нужно так - https://www.php.net/manual/ru/book.filter.php.

$("#commt").submit(function(){return false;}); - не так, а так:

$("#commt").submit(function(e){
    e.prevetDefault();
    //какие-то действия
    //ajax запрос и обработка ответа сервера
});


А этот обработчик $("#send_comments").on("click",function() ... удалить.

joyandjoy 22.10.2019 04:57

1. Старт сессии объявляется выше этого файла, здесь продолжение.
(капча работает, отдает верно/неверно по условию)
2. В моем случае нужна проверка только капчи, как это реализовать правильно?
3. Капча (php скрипт), и так работает над html формой
4. А что не так с фильтром? он же очищает все теги. Я так понимаю, можно использовать, number_int, но что-то не нашел более-менее понятных для меня примеров.

laimas 22.10.2019 05:58

Цитата:

Сообщение от joyandjoy
капча работает, отдает верно/неверно по условию

Вы что-то темните или ... Вот "все в одном"

<?
session_start();
//каптча
$_SESSION['check'] = rand(1, 9);
//обработка запроса
if(isset($_POST['test'])) exit('input: '.$_POST['test'].', check: '.$_SESSION['check']);
?>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
    $('input').keyup(function() {
        var f = this;
        $.post(location, {test: f.value}, function(d) {
            alert(d);
            f.value = ''
        })
    })    
});
</script>
</head>
<body>
<input />
</body>
</html>


и пока в нем строки 4 и 6 не поменять местами ввод будет равен каптче только если повезет. Почему, думаю, пояснять не надо.

Цитата:

Сообщение от joyandjoy
В моем случае нужна проверка только капчи

А остальное Пушкин проверять будет? Святая обязанность сервера фильтровать ввод, если вы не хотите все пустить на самотек. А делается это ну никак не trim вкупе с strip_tags.

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

joyandjoy 22.10.2019 06:32

Совсем запутался.
Насчет проверки, а что еще нужно проверять? Верно ли я понял что нужно использовать number_int? мы же очистим все кроме цифр, разве нет?
p.s. я ж не профи, очень многого не знаю :)
Кажется, я не правильно изначальную информацию дал
Вот полный файл:
Код:

<?php
$first = rand(1, 5); //получаем случайное значение
$second = rand(1, 5);
if ($first == $second) {//убираем возможность одинаковости первого и второго числа и исключаем тем самым нулевой результат
 $first = rand(1, 3);
 $second = rand(4, 5);
 }

 function mirror ($name, $name_l) //привязываем к выводимой в браузер ($first_l и $second_l) переменной текстовое значение в соответствии с используемой при вычислении
  {
$g = "1";
$r = "0";
  switch ($name) {
case 1:
    $name_l = "$g"; break;
    case 2:
    $name_l = "$r$g"; break;
case 3:
    $name_l = "$r$g$r"; break;
case 4:
    $name_l = "$r$g$r$g"; break;
case 5:
    $name_l = "$r$g$r$g$r"; break;
}
return $name_l;
 }
 
 $first_l = mirror ($first, $first_l); //инициализируем переменную
 $second_l = mirror ($second, $second_l);

// привязываем количество цвета к значению $first и $second
 function mirrorColor ($numvar){
    switch ($numvar) {
        case 1:
        $green = 1;
        $red = 0; break;   
    case 2:
        $green = 1;
        $red = 1; break;
    case 3:
        $green = 1;
        $red = 2; break;
    case 4:
        $green = 2;
        $red = 2; break;
    case 5:
        $green = 2;
        $red = 3; break;
    }
 return array ($green, $red);
 }
 
$f_color = mirrorColor ($first);// инициализируем массив
$s_color = mirrorColor ($second);

$gr_word = "<span style=color:green;font-weight:bolder>зеленых1</span>";
$red_word = "<span style=color:red;font-weight:bolder>красных0</span>";
 
$t = time();  //инициализируем переменную для смены операций временем в секундах на момент запроса
 
if ($t & 1) //меняем операцию в соответствии с четностью переменной
        {
          $_SESSION['res'] = $f_color['0'] + $s_color['0']; //заносим результат в сессионную переменную
                      $color = "$gr_word";//выводимое в браузер название цвета
        }
else
        {
          $_SESSION['res'] = $f_color['1'] + $s_color['1'];
                      $color = "$red_word";
        }
 

if (isset($_POST['result'])) { //если это был ответ


if (trim(strip_tags($_POST['result'])) == $_SESSION['res']) { //убираем, на всяки случай, теги и пробелы с обоих сторон и сравниваем результаты

$_SESSION['msg'] =  " Верно<br />";

 

$Lat = ["1"];

}
else {
$_SESSION['msg'] =  " Ошибка<br />";
$Lat = ["0"];
}
 
if (empty($_POST['result'])) {
$_SESSION['msg'] = " Нужно ввести ответ...<br />";
$Lat = ["0"];
}

 }
 
  ?>
 
 
<?


    <comments>

        <form method="post" name="uploader" enctype="multipart/form-data" id="commt">
                    <inline>

                            <div class="textarea">
                                    <textarea  name="text_comment" placeholder="<?echo $place_holder?>" required id="textAnsver_001"></textarea>
                                            <inline class="second"> 
                                                    <label><img src="<?echo$dir_blocks_http?>user.png" alt="ava" class="men"></label>
                                                    <input type="text" name="sended_name" required placeholder="Имя" value="<?echo$REAL_NAME?>" <?echo$disabled_name?> >         
                                                    <label><img src="<?echo$dir_blocks_http?>email.png" alt="email" class="email"></label>
                            <input type="email" name="sended_email" required  placeholder="Email" value="<?echo$REAL_EMAIL?>" <?echo$disabled_email?> >
                            <input type="hidden" name="img_hidden" required  placeholder="Email" value="">
 <input type="submit" id="submit" name=""  value="Отправить"/>                               
                                            </inline>

                                           
                            <!-- выводим текстовое описание примера //-->
Сколько <?=$color?> яблок?<br />
<?="$first_l$second_l"?> <br />
Ваш ответ: <input type="text" id="result" name="result" value="" style="width:17px; font-weight:bold;margin-top: 10px;" /><br />
    <!-- выводим соотв. сообщение //-->
<span style="background:yellow;"><?=$_SESSION['msg']?></span>

<!-- очищаем сесионную переменую сообщения //-->
<?php unset ($_SESSION['msg']);?>


                            </div>             
                    </inline>       
            </form>
    </comments>           
        </form>

Если у кнопки отобрать name="send_comments", то комментарий не отправляется, проходит только проверка капчи, и в выводе отдается информация верно не верно решение капчи (да, я понимаю, эта информация пользователю нужна только когда ответ неверен, но сейчас это для меня, чтобы было понятно работает или нет)
И да, капча как бы работает.

Цель вроде простая, средствами jqery сделать проверку на капчу, и в случае успеха отправить форму. Но вы говорите что еще и остальные поля надо проверить, но что и как...

laimas 22.10.2019 06:49

Цитата:

Сообщение от joyandjoy
Кажется, я не правильно

Это разве меняет логику, которая у вас в корне не верна?

Вот код что я давал:

<?
session_start();
//каптча
$_SESSION['check'] = rand(1, 9);
//обработка запроса
if(isset($_POST['test'])) exit('input: '.$_POST['test'].', check: '.$_SESSION['check']);
?>


Во-первых, и что понятно, он обязательно должен быть до вывода в браузер. Во-вторых, если сначала готовится каптча, сохраняется в сессии, а следующей операцией, это проверка равенства ее с вводом, то при каждом запросе клиента значение каптчи будет перезаписываться еще до проверки. Такая же неверная логика в коде и у вас, как может работать сначала:

$_SESSION['res'] = $f_color['1'] + $s_color['1'];

а затем:

if (trim(strip_tags($_POST['result'])) == $_SESSION['res']) ?

Верно, это:

<?
session_start();
//обработка запроса, с обязательным прекращением работы скрипта - exit
//иначе клиенту будет вывален код всей страницы
if(isset($_POST['test'])) exit('input: '.$_POST['test'].', check: '.$_SESSION['check']);
//каптча
$_SESSION['check'] = rand(1, 9);
?>


Либо, каптча готовится отдельным скриптом, к которому клиент обращается при загрузке страницы.

Цитата:

Сообщение от joyandjoy
Если у кнопки отобрать name="send_comments", то комментарий не отправляется

Я же спрашиваю, проверка каптчи это отдельная операция на разрешение отправления формы или нет? Если да, то делать нужно не так. Если вам нужен подобный вариант, то задействуйте уже готовое - recaptcha.

Для проверки каптчи не нужно никакого фильтра, достаточно проверки ввода с сохраненным на сервере. А вот для всего остального требуется фильтрация.

joyandjoy 22.10.2019 07:55

Цитата:

проверка каптчи это отдельная операция на разрешение отправления формы или нет?
Да. Хочется не рекапчту, а простую, свою.

Т.е. я изначально пошел не верным путем решив все засунуть в один файл? Вообще вот та самая капча которую хочу - http://coderhs.com/archive/captcha_math_text (последнее).

laimas 22.10.2019 07:58

Ну так разницу видите? Там каптча, это отдельный от обработчика формы файл, а вы скрестили все в одно, но порядок скриптов при этом неверный, а каков правильный должен быть порядок я уже писал выше.

joyandjoy 22.10.2019 08:04

Ошибку понял. Но как сделать проверку посредством jqery? как обратиться к файлу с ответом от капчи и при верном условии, форму отправить?

laimas 22.10.2019 08:13

Делать отдельный запрос для проверки каптчи, при этом не обязательно код каптчи должен быть отдельным файлом, ибо имя у поля каптчи, а это ключ на сервере, свое, значит даже расположив в одном файле прием запроса каптчи и запрос формы, по имени ключа в запросе можно определить что интересует клиента.
Нужно только выполнить два обязательных условия:
1) Обработка асинхронных запросов клиента должна быть в самом начале файле, а при работе с сессией после ее продолжения.
2) Код обработки запроса должен заканчиваться завершением работы скрипта функцией exit. Ответ клиенту при этом может быть аргументом данной функции, если ответ это строка, которая будет выведена в браузер. Если этой функции передать число, то это будет принято как код завершения и вывода в браузер не будет.

laimas 22.10.2019 11:33

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

1) Согласно условиям ранее оговоренным:

<?
session_start();
//обработка запросов
if($_POST) {
    switch($k = key($_POST)) {
        case 'check': $out = $_SESSION['check']==(int)$_POST[$k] ? '' : 'Завтра в школу с родителями!';
        break;
        case 'text': $out = 'Ok';
    }
    exit($out);    
}
//каптча
$a = ['+','-','*'];
shuffle($a);
$check = rand(1, 10) . $a[0] . rand(1, 10);
eval('$_SESSION[check]='.$check.';');
?>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
    $('button').click(function() {
        $.post(location, {check: $(this).prev().val()}, function(d) {
            if(!d) $('form').submit();
            else alert(d);
        })
    });
    
    $('form').submit(function(e) {
        e.preventDefault();
        $.post(location, $(this).serialize(), function(d) {
            alert(d)
        })    
    });
});
</script>
</head>
<body>
<form>
<input name="text" value="Text" />
</form>
<span>Сколько: <?=$check?>=?</span>
<input name="check" />
<button>Проверка</button>
</body>
</html>


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

2) Генерация каптчи функцией и обмен с сервером в формате JSON.

<?
session_start();
//каптча
function check() {
    $a = ['+','-','*'];
    shuffle($a);
    $check = rand(1, 10) . $a[0] . rand(1, 10);
    eval('$_SESSION[check]='.$check.';');
    return $check;
}
//обработка запросов
if($_POST) {
    switch($k = key($_POST)) {
        case 'check': $out = $_SESSION['check']==(int)$_POST[$k] ? '' : ['err'=>1, 'exp'=>check(), 'msg'=>'Двойка! Завтра в школу с родителями!'];
        break;
        case 'text': $out = ['exp'=>check(), 'msg'=>'Ok!'];
    }
    exit(json_encode($out));    
}
?>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
    $('button').click(function() {
        var f = $(this).prev();
        $.post(location, {check: f.val()}, function(d) {
            if(!d.err) $('form').submit();
            else {
                $('span').text(d.exp);
                f.val('');
                alert(d.msg);
            }
        }, 'json')
    });
    
    $('form').submit(function(e) {
        e.preventDefault();
        $.post(location, $(this).serialize(), function(d) {
            $('span').text(d.exp);
            $('[name="check"]').val('');
            alert(d.msg);
        }, 'json')    
    });    
});
</script>
</head>
<body>
<form>
<input name="text" value="Text" />
</form>
<label>Сколько: <span><?=check()?></span>=?</label>
<input name="check" />
<button>Проверка</button>
</body>
</html>

joyandjoy 22.10.2019 12:13

Однако казалось легче изначально :)
Обманчивая и страшная штука этот JS.
Пойду экспериментировать.
Цитата:

Но при таком решении затруднительно обновлять каптчу при ошибках и после приема формы. Но достаточно генерацию каптчи сделать функцией
В желаемом мной варианте как раз таки она и в виде функции как я понимаю.

laimas 22.10.2019 12:21

Цитата:

Сообщение от joyandjoy
В желаемом мной варианте как раз таки она и в виде функции как я понимаю

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

И у вас проблемы прежде всего в этом, в структуре кода вашего, а не в JS.


Часовой пояс GMT +3, время: 22:26.