Поэтому у меня есть веб-приложение, над которым я работаю, с формой, которая требует заполнения всех полей перед отправкой. Если вы попытаетесь отправить приложение без заполнения поля, он снова загрузит страницу с ошибками. Как только вы заполните все поля и нажмите «Отправить», он перенаправляется на одну страницу и отображает сообщение, которое генерируется из flashdata. См. Упрощенный пример ниже.
Контроллер приветствия:
function show_view() { $this->load->view('form'); } function process_form() { // make the 'quality' field required $this->form_validation->set_rules('quality', 'Quality', 'required'); if($this->form_validation->run() == FALSE) //if the fields are NOT filled in... { echo form_error('quality'); $this->load->view('form'); //reload the page } else // if the fields are filled in... { // set success message in flashdata so it can be called when page is refreshed. $this->session->set_flashdata('message', 'Your rating has been saved'); redirect(welcome/show_view); } }
Теперь, чтобы проиллюстрировать мою проблему, скажем, я нахожусь в «домашнем» представлении, и я перехожу к представлению «форма». Если я заполню поле «качество» и нажмите «Отправить», я вернусь обратно к представлению «форма» с сообщением об успешном завершении. Если я нажму кнопку «Назад» в браузере, он вернет меня в «домашний» вид. ВСЕ РАБОТАЕТ КАК ОЖИДАЕТСЯ
Теперь скажем, что я нахожусь в «домашнем» представлении, и я перехожу к представлению «форма». Если я нажму кнопку «Отправить», не заполняя поле «качество», вид «форма» снова перезагрузится и отобразится сообщение об ошибке. Если я заполнил поле «качество» и нажал кнопку «Отправить», я вернусь к представлению «форма» с сообщением об успешном завершении. Проблема в том, что если я нажму кнопку «Назад» в браузере, теперь она вернет меня на страницу формы с ошибкой, и я снова должен нажать кнопку «Назад», чтобы вернуться в «домашний» вид.
Какая наилучшая практика кодирования, так что если пользователь отправляет форму с ошибками, она отображает ошибки, и если они исправят ошибки и снова отправят форму, она отобразит сообщение об успешном завершении и, если они вернутся в браузер, это вернет их в «домашний» вид?
Проблема в том, что вы используете две отдельные функции для обработки форм. Документы класса проверки формы не очень хорошо объясняют это, и мне потребовалось некоторое время, чтобы понять это, но form_validation-> run () возвращает false, если есть ошибка, но также, если это запрос GET, и впоследствии учитывает запрос GET в связанных функциях, таких как form_error () и validation_errors (), set_value () и т. д.
Наилучшая практика в CI (и в целом) заключается в том, чтобы сделать это:
class Welcome extends CI_Controller{ function home(){ $this->load->view('home'); } function form() { // make the 'quality' field required $this->form_validation->set_rules('quality', 'Quality', 'required'); // If the fields are NOT filled in... // or if there isn't a POST! (check the Form_validation.php lib to confirm) if ( $this->form_validation->run() === FALSE) { // This form_error() function actually doesn't do anything if there // wasn't a form submission (on a GET request) echo form_error('quality'); $this->load->view('form'); // load or reload the page } else // if the fields are filled in... { // set success message in flashdata so it can be // called when page is redirected. $this->session->set_flashdata('message', 'Your rating has been saved'); redirect('welcome/home','location', 303); exit; } }
то в представлении есть форма action="welcome/form"
В основном все функции ошибки формы и все материалы, связанные с проверкой формы, имеют проверки, чтобы проверить, действительно ли работает проверка подлинности формы … вот пример из функции form_error в вспомогательном файле формы
function form_error($field = '', $prefix = '', $suffix = '') { if (FALSE === ($OBJ =& _get_validation_object())) { return ''; } return $OBJ->error($field, $prefix, $suffix); }
Когда они не являются POST, он показывает как обычно, и имеет естественный поток страниц, который вы ищете.
Не связанный с вопросом, но запутанный / примечательный о классе проверки формы … если вы используете фильтры, такие как xss_clean, prep_url и т. Д. В поле параметров, он фактически репопулирует массив $ _POST для вас, так что вы действительно не используете нужно сделать что-нибудь дополнительное.
Иногда стоит взглянуть на внутренности источника CI, там есть какие-то умные вещи, которые не совсем очевидны.
Я ожидаю, что форма переадресует меня на страницу списка ресурсов, где ресурс – это объект, который пользователь отправляет изначально.
Если пользователь добавляет новую запись в ресурс, они ожидают увидеть запись в листинге после успешной отправки формы.
Если форма находится на одной странице, вы все равно должны будете перенаправить на основе местоположения вместо обновления http. Код состояния для этого варианта использования – 303 См . Раздел «Прочее» .
через код HTTP 303 Википедии
Вот что я сделал бы, учитывая ваш сценарий.
function home(){ $this->load->view('home'); } function show_view() { $this->load->view('form'); } function process_form() { // make the 'quality' field required $this->form_validation->set_rules('quality', 'Quality', 'required'); if($this->form_validation->run() === FALSE) //if the fields are NOT filled in... { echo form_error('quality'); $this->load->view('form'); //reload the page } else // if the fields are filled in... { // set success message in flashdata so it can be called when page is redirected. $this->session->set_flashdata('message', 'Your rating has been saved'); redirect('welcome/home','location', 303); exit; } }
Я использую Symfony некоторое время, и я думаю, что решение Symfony является оптимальным. То, как он работает, – это то, что у вас есть маршруты (я думаю, что у CI есть маршруты тоже: CI-маршруты ), и в вашем контроллере вы можете сделать что-то подобное в своем методе «create»:
if the form is valid set flash notice message redirect to (your homepage or something else defined in your routing file) else set flash error message set the current view to form
Действие вашей формы – это один и тот же контроллер с действием «create» (доступ к которому возможен только через запрос POST). Форма, которую вы можете получить с помощью запросов GET, – это «новый» метод. Поэтому, если вы нажмете кнопку «Отправить» в своей форме, перейдите к методу create, но новый метод впервые сформирует вашу форму. Если ваша форма не подтверждается, вы остаетесь там с сообщениями об ошибках. Если вы нажмете назад, вы получите новую форму, но если форма проверяет ваше действие (метод) перенаправляет на пользовательскую страницу, которую вы указали ранее в приведенном выше выражении if.
Этот метод также работает с ajax, вы можете проверить свое действие, если запрос является XHTTP, вы просто возвращаетесь, если форма проверяется или нет, и вы можете обрабатывать вещи в javascript. Я думаю, что это лучший способ обработки форм, и если у вашего пользователя нет javascript, он все равно может использовать «стандартный» способ. И кстати: «create» и «new» использует один и тот же шаблон (view). Надеюсь, что я все понял.
Единственный надежный способ сообщить браузеру игнорировать / удалять страницы в своей истории с помощью команды javascript:
location.replace(url);
это перенаправляет клиентскую сторону, но заменяет текущее местоположение в истории вашего браузера. Или, альтернативно, не перейти на новую страницу вообще (ajax-вызов).
Если вы используете POST в качестве метода в своей форме, они получат сообщение о том, что им нужно повторно отправить информацию на сервер, чтобы вернуться, что избавит большинство людей от использования кнопки «Назад».
Вы можете использовать шаблон nonce, в котором вы создаете отметку времени или другой уникальный идентификатор, помещаете его в сеанс и скрытое поле в своей функции show_view при создании формы, а затем проверяете соответствие ее функции процесса и удаляете ее из сеанс, если есть совпадение. Таким образом, если они попытаются отправить одну и ту же форму дважды (нажав кнопку «Назад»), вы можете обнаружить ее, увидев, что нет совпадения, и перенаправлять их на беспроигрышный show_view или домашнюю страницу или где бы вы ни захотели.
Вы также захотите удостовериться, что ваши истекающие и заголовки кеша-контроля заставляют веб-браузер нападать на сервер каждый раз, а не просто использовать его локальный кеш. http://www.web-caching.com/mnot_tutorial/notes.html#IMP-SERVER
Для игроков или хуже, большинство веб-сайтов игнорируют проблемы с кнопками «Назад», такие как эти
Объект окна DOM предоставляет доступ к истории браузера через объект истории. Он предоставляет полезные методы и свойства, которые позволяют перемещаться вперед и назад по истории пользователя, а также – начиная с HTML5 – манипулировать содержимым стека истории. https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history
Другое дело – отправить форму с помощью ajax! и заполнять сообщение об ошибках или успешное сообщение на основе ответа … (XML, JSON ..), конечно, это не совсем то, что вы искали, но оно имеет много преимуществ в пользовательском интерфейсе, которое вы пытаетесь улучшить.
Если это вообще возможно, избегайте перенаправления и на странице отображается тот же контент, что и при его перенаправлении. Таким образом, браузеры не будут рассматривать несколько представлений как разные страницы.
Кроме того, новый JavaScript-код HTML5 имеет изменение состояния истории или любое другое его имя. Таким образом, вы можете определить в своей программе, как сайт должен вести себя к изменениям страницы через кнопку «Назад» и … вскоре вы увидите множество кнопок с обратной связью, интегрированных в веб-интерфейс.
Самый простой способ сделать то, что вы предлагаете, – отправить значения формы на ваш валидатор PHP с помощью HTTPRequest (AJAX), а затем показать ошибки с помощью JavaScript. Таким образом вам не нужно будет перенаправлять, а кнопка «Назад» по-прежнему приведет вас домой.
Если вы настаиваете на использовании перенаправления, у меня есть несколько идей, но ни один из них не является элегантным. Может, у кого-то есть идея?
Хотя я бы рекомендовал использовать форму представления AJAX в качестве решения этой проблемы.
Насколько я знаю – и вы можете найти – нет надежного способа поймать событие истории, и все решения основаны на Javascript, поэтому вы можете создать форму AJAX. Я бы сказал, что единственным возможным решением, отличным от javascript, будет либо iframe (которому никто не любит), ни то, что предлагает BraedenP.
Лично, если вы действительно хотите эту функциональность, я бы создал форму AJAX и просто не работал так для пользователей, не являющихся javascript (их следует использовать, чтобы иметь немного менее оптимизированный опыт).
Это всегда хорошая практика, чтобы добавить на ваш сайт цепочку для поиска или возврата на задний план, чтобы это тоже помогло.