Цитата:
|
На клиенте:
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <style> .container { width: 30%; margin: 0 auto; } .container h3:before { content: attr(data-quest); } .container.send h3:before { content: attr(data-send); } .container.done h3:before { content: attr(data-done); } .container.error h3:before { content: attr(data-error); color: #f00; } .container .next { visibility: hidden; } .container:not(.send) .next { visibility: visible; } form { position: relative; } form * { box-sizing: border-box; } input, select, textarea { width: 100%; } textarea { resize: vertical; height: 130px; } /*цвет списка не выбранного*/ select:invalid { color: #767676; } /*но только не его доступных опций*/ select:invalid option:not(:disabled) { color: #000; } .overlap { display: none; position: absolute; top: 0; left: 0; width: 100%; height: 100%; padding: 30px; background-color: rgba(1, 34, 77, 0.93); z-index: 5; } .container.send .overlap, .container.done .overlap, .container.error .overlap { display: block; } .overlap ul { padding: 0; margin-top: 20px; } .overlap li { list-style: none; font-size: 18px; color: #fff; } .progress { display: none; justify-content: center; align-items: center; height: 100%; overflow: hidden; } .container.send .progress { display: flex; } .circle { width: 20px; height: 20px; border-radius: 50%; margin: 7px; display: flex; justify-content: center; align-items: center; } .circle:before { content: ""; width: 20px; height: 20px; border-radius: 50%; opacity: 0.7; animation: scale 2s infinite cubic-bezier(0, 0, 0.49, 1.02); } .circle-1 { background-color: #49b8e5; } .circle-1:before { background-color: #49b8e5; animation-delay: 200ms; } .circle-2 { background-color: #1e98d4; } .circle-2:before { background-color: #1e98d4; animation-delay: 400ms; } .circle-3 { background-color: #2a92d0; } .circle-3:before { background-color: #2a92d0; animation-delay: 600ms; } .circle-4 { background-color: #3a88c8; } .circle-4:before { background-color: #3a88c8; animation-delay: 800ms; } .circle-5 { background-color: #507cbe; } .circle-5:before { background-color: #507cbe; animation-delay: 1000ms; } @keyframes scale { 0% { transform: scale(1); } 50%, 75% { transform: scale(2.5); } 78%, 100% { opacity: 0; } } </style> </head> <body> <div class="container"> <h3 data-quest="Задать вопрос" data-send="Отправление формы" data-done="Форма отправлена" data-error="Ошибки приема данных"></h3> <form id="feedback" method="post" action="/feedback/mails_sender.php" enctype="multipart/form-data" autocomplete="off"> <div class="comment"> <fieldset> <select name="sex" required=""> <option value="" selected="" disabled="">Выберите Ваш пол *</option> <option value="1">Мужчина</option> <option value="3">Женщина</option> </select> </fieldset> <fieldset> <input name="email" type="email" placeholder="Эл. @ почта *" required="" /> </fieldset> <fieldset> <select name="worker" required=""> <option value="" selected="" disabled="">Выберите сотрудника *</option> <option value="1">Сергей</option> <option value="2">Иван</option> <option value="a">Николай</option> <option value="4">Антон</option> <option value="5">Виктор</option> </select> </fieldset> <fieldset> <input name="subject" type="text" placeholder="Тема *" required="" /> </fieldset> <fieldset> <textarea name="message" placeholder="Текст сообщения *" required=""></textarea> </fieldset> <fieldset> <input type="file" name="file" /> </fieldset> </div> <div class="buttons"> <button type="submit" class="sub">Отправить</button> <button type="reset" class="sub">Очистить</button> </div> <div class="overlap"> <div class="progress"> <div class="circle circle-1"></div> <div class="circle circle-2"></div> <div class="circle circle-3"></div> <div class="circle circle-4"></div> <div class="circle circle-5"></div> </div> <ul class="response"></ul> <button class="next" type="button">Продолжить</button> </div> </form> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script> var frm = $("#feedback").submit(function(e) { e.preventDefault(); //отменяем действие по умолчанию var container = $('.container'), //контейнер data = new FormData; //данные для отправления //помещаем поля формы в data $.each(frm.serializeArray(), function() { data.append(this.name, this.value) }); //если есть выбор файла, добавляем его в data if(this.file.value) data.append('file', this.file.files[0]); $.ajax({ url: this.action, type: 'post', dataType: 'json', data: data, cache: false, contentType: false, processData: false, beforeSend: function() { container.addClass('send') //показываем прогресс }, complete: function() { container.removeClass('send') //удаляем прогресс }, success: function(resp) { //определяем вывод сообщения в заголовке container.addClass(resp.result); //выводим результат отправления frm.find('ul.response').html('<li>' + resp.data.join('</li><li>') + '</li>') }, error: function(xhr, opt, error) { alert(error + "\n" + xhr.statusText + "\n" + xhr.responseText); } }) }).find('button.next').click(function() { //сбросить форму если нет ошибок if(!frm.parent().hasClass('error')) frm.find('[type="reset"]').click(); //убираем перекрытие формы frm.parent().removeClass('done error').find('ul.response').empty() }).end(); </script> </body> </html> На просторах интернета "крутилок" как собак ... здесь одна из них, если есть беспокойство о древних браузерах, тогда гифки. Вывод действа в заголовок формы, который определяется его data атрибутами и текущим именем родительского контейнера. Остальное не требует пояснения, надеюсь, это простой минимум, которого вполне хватает для отправления, "жир наращивать", это уже по вкусу и потребностям. Полям добавлен атрибут required поэтому будет нативная проверка браузером и пустая форма отправляется не будет. Значения списков не могут быть Сергей, Петя ... это должны быть идентификаторы, которые сервер проверяет. Собственно и в список Пол вставлять в значения мужчина/женщина, это от лени. |
На сервере:
<?php //задержка для посмотерть как работает форма при отправке, удалить после sleep(2); $check = [ 'sex' => [ 'filter' => FILTER_VALIDATE_INT, //пол, это вообще-то поле типа ENUM в базе со значениями: 1 - мужчина, 2 - женщина, это и надо проверять 'flags' => FILTER_REQUIRE_SCALAR, 'options' => ['min_range' => 1, 'max_range' => 2] ], 'email' => FILTER_VALIDATE_EMAIL, 'worker' => FILTER_VALIDATE_INT, //сотрудник Петя может быть таким только как текст опции, но никак не ее значение, значением должен быть уникальный идентфикатор сотрудника 'subject' => [ 'filter' => FILTER_VALIDATE_REGEXP, 'options' => ['regexp' =>'/^[а-яё\s]{10,60}$/ui'] ], 'message' => FILTER_SANITIZE_SPECIAL_CHARS //нет смысла в strip_tags, если отправление в html формате, лучше преобразовать в html сущности ]; $error_message = [ 'sex' => 'Некорректное значение поля «Пол»!', 'email' => 'Некорректное значение поля «Адрес почты»!', 'worker' => 'Некорректное значение поля «Сотрудник»!', 'subject' => 'Некорректное значение поля «Тема»!', 'message' => 'Некорректное значение поля «Сообощение»!', 'file' => 'Ошибка получения файла!' ]; $errors = []; //убираем возможные крайние пробелы $post = array_map('trim', $_POST); //если не все на месте, нарушение формы, это не наш клиент, в этом случае можно прекратить работу и выйти if(array_diff_key($post, $check)) exit; //проверяем что прислали $data = filter_var_array($post, $check); //если есть ошибки получим их сообщения $errors += array_intersect_key($error_message, array_filter($data, function($v) { return !$v; })); //если прикреплен файл if(!empty($_FILES)) { if(!$_FILES['error']) { //другие проверки файла - тип, размер и прочее что нужно } else $errors += array_intersect_key($error_message, array_flip(array_keys($_FILES))); //если ошибка загрузки файла } //отправляем ошибки клиенту if($errors) { header('Content-Type: application/json'); exit(json_encode(['result'=> 'error', 'data'=> array_values($errors)])); } else { //имитация базы $sex = [1 => 'мужчина', 'женщина']; $worker = [1 => 'Сергей', 'Иван', 'Николай', 'Антон', 'Виктор']; //получаем имя сотрудника запросом к базе по его ID, проверяя заодно есть ли такой //здесь проверка имитация, проверяется наличие ключа в $worker if(!$name = $worker[$data['worker']]) exit; //выход, нет такого сотрудника, форма левая //хороший тон, это отправление и текстовой версии, так как неизвестно в каком формате адресат принимает почту $text = 'Текстовый вариант'; //html версия $html = "<p><b>Пол:</b> {$sex[$data[sex]]}</p> <p><b>E-mail:</b> {$data[email]}</p> <p><b>Сотрудник:</b> $name</p> <p><b>Сообщение:</b> {$data[message]}</p>"; $to = 'pochta@mail.ru'; $subject = '=?utf-8?b?' . base64_encode($data['subject']) . '?='; $headers = 'From: =?utf-8?B?' . base64_encode($name) . '?= <' . $data['email'] . '>' . PHP_EOL; $headers .= 'Reply-To: receiver@domain3.com' . PHP_EOL; $headers .= 'X-Mailer: PHP/' . phpversion() . PHP_EOL; $headers .= 'Mime-Version: 1.0' . PHP_EOL; $headers .= 'Content-Type: multipart/alternative; boundary="==boundary-2"' . PHP_EOL.PHP_EOL; $body .= '--==boundary-2' . PHP_EOL.PHP_EOL; $body .= 'Content-type: text/plain; charset="utf-8"' . PHP_EOL; $body .= 'Content-Transfer-Encoding: 8bit' . PHP_EOL.PHP_EOL; $body .= $text . PHP_EOL; //текстовая версия $body .= '--==boundary-2' . PHP_EOL; $body .= 'Content-Type: multipart/related; boundary="==boundary-1"; type="text/html"' . PHP_EOL.PHP_EOL; $body .= '--==boundary-1' . PHP_EOL; $body .= 'Content-type: text/html; charset="utf-8"' . PHP_EOL; $body .= 'Content-Transfer-Encoding: base64' . PHP_EOL.PHP_EOL; $body .= chunk_split(base64_encode($html)) . PHP_EOL.PHP_EOL; //html версия $body .= !empty($_FILES) ? '--==boundary-1' . PHP_EOL : '--==boundary-1--' . PHP_EOL; if(!empty($_FILES)) { $f = fopen($_FILES['file']['tmp_name'], 'rb'); $body .= 'Content-Type: image/jpeg' . PHP_EOL; //заголовок произвольный, а вообще нужно проверять тип и его указывать, в случае изображения его можно встроить непосредственно в письмо $body .= 'Content-Transfer-Encoding:base64' . PHP_EOL; $body .= 'Content-Disposition: inline; filename="' . basename($_FILES['file']['name']) . '"' . PHP_EOL.PHP_EOL; $body .= chunk_split(base64_encode(fread($f, filesize($_FILES['file']['tmp_name'])))); $body .= '--==boundary-1--' . PHP_EOL; } $body .= '--==boundary-2--' . PHP_EOL; mail($to, $subject, $body, $headers); //функция mail не знает о том отправлено ли письмо или нет, она лишь сообщает о факте его принятия для отправления программой sendmail header('Content-Type: application/json'); exit(json_encode(['result'=> 'done', 'data'=> ['Письмо отправлено']])); } А вообще используйте готовые библиотеки, которые более серьезно к этому подходят, например phpmailer. Она отправляет и по SMTP, что не мало важно в нынешнее время, когда не редкость в отказе хостов к доступу функции mail из-за вала спама захлестнувшего почту, только SMTP. |
В двух списках специально некорректные значения - в списке Пол у женщины, 3 вместо 2, и не цифровое значение в списке Сотрудники у опции Николай, чтобы проверить.
|
Спасибо за помощь.
1. При отправке проверяет все поля, кроме поля Текст. Его можно отправить пустым. 2. После нажатия на кнопку "Отправить" белая страница! Ругается на PHP Parse error: syntax error, unexpected '[' in /feedback/mails_sender3.php on line 5В файле mails_sender3.php размещена серверная часть. 3. Помогите убрать поля Тема и Загрузка файла, они не нужны. Можно ли вместо них прикрутить какую-нибудь капчу, чтобы спамеры не доставали? |
Цитата:
PHP Parse error: syntax error, unexpected '[' - старая версия РНР, ниже 5.4. Собственно [], это сокращенная запись array(), которая доступна с версии 5.4. Либо выберите версию выше, либо замените это на array(). Помогите убрать поля Тема и Загрузка файла, они не нужны. - просто уберите их из формы, из фильтров уберите проверку поля темы письма и определите свой текст, но до его кодирования, и удалите все что касается загрузки файла. А каптча, это лучше использовать готовые решения, например от Гугла, а как ее подключить, это в сети найдете. Вы показываете код, в котором все, а затем только начинаются уточнения - это не надо, тут не то ... |
Посмотрите пожалуйста правильно ли поменял [ на array(
В строке 88 и далее что-то не так. Я не понял как там менять <?php //задержка для посмотерть как работает форма при отправке, удалить после sleep(2); $check = array( 'sex' => array( 'filter' => FILTER_VALIDATE_INT, //пол, это вообще-то поле типа ENUM в базе со значениями: 1 - мужчина, 2 - женщина, это и надо проверять 'flags' => FILTER_REQUIRE_SCALAR, 'options' => array('min_range' => 1, 'max_range' => 2) ), 'email' => FILTER_VALIDATE_EMAIL, 'worker' => FILTER_VALIDATE_INT, //сотрудник Петя может быть таким только как текст опции, но никак не ее значение, значением должен быть уникальный идентфикатор сотрудника 'subject' => array( 'filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' =>'/^(а-яё\s){10,60}$/ui') ), 'message' => FILTER_SANITIZE_SPECIAL_CHARS //нет смысла в strip_tags, если отправление в html формате, лучше преобразовать в html сущности ); $error_message = array( 'sex' => 'Некорректное значение поля «Пол»!', 'email' => 'Некорректное значение поля «Адрес почты»!', 'worker' => 'Некорректное значение поля «Сотрудник»!', 'subject' => 'Некорректное значение поля «Тема»!', 'message' => 'Некорректное значение поля «Сообощение»!', 'file' => 'Ошибка получения файла!' ); $errors = array(); //убираем возможные крайние пробелы $post = array_map('trim', $_POST); //если не все на месте, это не наш клиент, в этом случае можно прекртить работу и выйти if(array_diff_key($post, $check)) exit; //проверяем что прислали $data = filter_var_array($post, $check); //если есть ошибки получим их сообщения $errors += array_intersect_key($error_message, array_filter($data, function($v) { return !$v; })); //если прикреплен файл if(!empty($_FILES)) { if(!$_FILES('error')) { //другие проверки файла - тип, размер и прочее что нужно } else $errors += array_intersect_key($error_message, array_flip(array_keys($_FILES))); //если ошибка загрузки файла } //отправляем ошибки клиенту if($errors) { header('Content-Type: application/json'); exit(json_encode(array('result'=> 'error', 'data'=> array_values($errors)))); } //имитация базы $sex = array(1 => 'мужчина', 'женщина'); $worker = array(1 => 'Сергей', 'Иван', 'Николай', 'Антон', 'Виктор'); //если нет ошибок if(!$errors) { //получаем имя сотрудника запросом к базе по его ID, проверяя заодно есть ли такой //здесь проверка имитация, проверяется наличие ключа в $worker if(!$name = $worker($data('worker'))) exit; //выход, нет такого сотрудника, форма левая //хороший тон, это отправление и текстовой версии, так как неизвестно в каком формате адресат принимает почту $text = 'Текстовый вариант'; //html версия $html = "<p><b>Пол:</b> {$sex($data(sex))}</p> <p><b>E-mail:</b> {$data(email)}</p> <p><b>Сотрудник:</b> $name</p> <p><b>Сообщение:</b> {$data(message)}</p>"; $to = 'pocta@mail.ru'; $subject = '=?utf-8?b?' . base64_encode($data('subject')) . '?='; $headers = 'From: =?utf-8?B?' . base64_encode($name) . '?= <' . $data('email') . '>' . PHP_EOL; $headers .= 'Reply-To: receiver@domain3.com' . PHP_EOL; $headers .= 'X-Mailer: PHP/' . phpversion() . PHP_EOL; $headers .= 'Mime-Version: 1.0' . PHP_EOL; $headers .= 'Content-Type: multipart/alternative; boundary="==boundary-2"' . PHP_EOL.PHP_EOL; $body .= '--==boundary-2' . PHP_EOL.PHP_EOL; $body .= 'Content-type: text/plain; charset="utf-8"' . PHP_EOL; $body .= 'Content-Transfer-Encoding: 8bit' . PHP_EOL.PHP_EOL; $body .= $text . PHP_EOL; //текстовая версия $body .= '--==boundary-2' . PHP_EOL; $body .= 'Content-Type: multipart/related; boundary="==boundary-1"; type="text/html"' . PHP_EOL.PHP_EOL; $body .= '--==boundary-1' . PHP_EOL; $body .= 'Content-type: text/html; charset="utf-8"' . PHP_EOL; $body .= 'Content-Transfer-Encoding: base64' . PHP_EOL.PHP_EOL; $body .= chunk_split(base64_encode($html)) . PHP_EOL.PHP_EOL; //html версия $body .= !empty($_FILES) ? '--==boundary-1' . PHP_EOL : '--==boundary-1--' . PHP_EOL; if(!empty($_FILES)) { $f = fopen($_FILES('file')('tmp_name'), 'rb'); $body .= 'Content-Type: image/jpeg' . PHP_EOL; //заголовок произвольный, а вообще нужно проверять тип и его указывать, в случае изображения его можно встроить непосредственно в письмо $body .= 'Content-Transfer-Encoding:base64' . PHP_EOL; $body .= 'Content-Disposition: inline; filename="' . basename($_FILES('file')('name')) . '"' . PHP_EOL.PHP_EOL; $body .= chunk_split(base64_encode(fread($f, filesize($_FILES('file')('tmp_name'))))); $body .= '--==boundary-1--' . PHP_EOL; } $body .= '--==boundary-2--' . PHP_EOL; mail($to, $subject, $body, $headers); //функция mail не знает о том отправлено ли письмо или нет, она лишь сообщает о факте его принятия для отправления программой sendmail header('Content-Type: application/json'); exit(json_encode(array('result'=> 'done', 'data'=> array('Письмо отправлено')))); } |
:)
Ну тут: $check = array( 'sex' => array( ... и до конца все верно, но !$_FILES('error') так и должно быть !$_FILES['error'], как и $data('worker') должно быть $data['worker'], и {$sex[$data[sex]]}, и т.д., и т.п., так как это не объявление массива, а обращение к элементу массива по ключу/индексу, и это пишется именно в квадратных скобках. |
Но коли вам не нужно вложения файлов, то проверку его
if(!empty($_FILES)) { if(!$_FILES('error')) { //другие проверки файла - тип, размер и прочее что нужно } else $errors += array_intersect_key($error_message, array_flip(array_keys($_FILES))); //если ошибка загрузки файла } можно удалить. В почте строку $body .= !empty($_FILES) ? '--==boundary-1' . PHP_EOL : '--==boundary-1--' . PHP_EOL; заменить на $body .= '--==boundary-1--' . HP_EOL; Удалить начиная с if(!empty($_FILES)) { и по закрывающую } |
PHP Parse error: syntax error, unexpected $end in /feedback/mails_sender3.php on line 102это самая последняя строка } |
Часовой пояс GMT +3, время: 15:19. |