Вопрос

Вы когда-нибудь натыкались на учебник, который, по вашему мнению, имеет большую ценность, но не совсем правильно объяснен?Это моя дилемма.Я знаю ЭТОТ РУКОВОДСТВО имеет некоторую ценность, но я просто не могу ее получить.

  1. Где вы вызываете каждую функцию?
  2. Какая функция должна быть названа первой, а какая следующая, а какая третья?
  3. Будут ли вызываться все функции во всех файлах приложения?
  4. Кто-нибудь знает лучший способ вылечить «блюз кнопки «Назад»»?

Мне интересно, вызовет ли это какой-нибудь хороший разговор с участием автора статьи.Часть, которая меня особенно интересует, — это управление кнопкой «Назад», чтобы предотвратить дублирование записей в базе данных при нажатии кнопки «Назад».По сути, вы хотите управлять кнопкой «Назад», вызывая следующие три функции во время выполнения сценариев в вашем приложении.В каком именно порядке вызывать функции (см. вопросы выше) из туториала не понятно.

Все движения Forwards выполняется с помощью моей функции ScriptNext.Это вызывается в текущем сценарии, чтобы активировать новый сценарий.

function scriptNext($script_id)
// proceed forwards to a new script
{
   if (empty($script_id)) {
      trigger_error("script id is not defined", E_USER_ERROR);
   } // if

   // get list of screens used in this session
   $page_stack = $_SESSION['page_stack'];
   if (in_array($script_id, $page_stack)) {
      // remove this item and any following items from the stack array
      do {
         $last = array_pop($page_stack);
      } while ($last != $script_id);
   } // if

   // add next script to end of array and update session data
   $page_stack[] = $script_id;
   $_SESSION['page_stack'] = $page_stack;

   // now pass control to the designated script
   $location = 'http://' .$_SERVER['HTTP_HOST'] .$script_id;
   header('Location: ' .$location); 
   exit;

} // scriptNext

Когда любой сценарий завершил свою обработку, его завершает, вызывая мою сценарию.Это отбросит текущий сценарий с конца массива стека и повторно активирует предыдущий сценарий в массиве.

function scriptPrevious()
// go back to the previous script (as defined in PAGE_STACK)
{
   // get id of current script
   $script_id = $_SERVER['PHP_SELF'];

   // get list of screens used in this session
   $page_stack = $_SESSION['page_stack'];
   if (in_array($script_id, $page_stack)) {
      // remove this item and any following items from the stack array
      do {
         $last = array_pop($page_stack);
      } while ($last != $script_id);
      // update session data
      $_SESSION['page_stack'] = $page_stack;
   } // if

   if (count($page_stack) > 0) {
      $previous = array_pop($page_stack);
      // reactivate previous script
      $location = 'http://' .$_SERVER['HTTP_HOST'] .$previous;
   } else {
      // no previous scripts, so terminate session
      session_unset();
      session_destroy();
      // revert to default start page
      $location = 'http://' .$_SERVER['HTTP_HOST'] .'/index.php';
   } // if

   header('Location: ' .$location); 
   exit;

} // scriptPrevious

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

function initSession()
// initialise session data
{
   // get program stack
   if (isset($_SESSION['page_stack'])) {
      // use existing stack
      $page_stack = $_SESSION['page_stack'];
   } else {
      // create new stack which starts with current script
      $page_stack[] = $_SERVER['PHP_SELF'];
      $_SESSION['page_stack'] = $page_stack;
   } // if

   // check that this script is at the end of the current stack
   $actual = $_SERVER['PHP_SELF'];
   $expected = $page_stack[count($page_stack)-1];
   if ($expected != $actual) {
      if (in_array($actual, $page_stack)) {// script is within current stack, so remove anything which follows
      while ($page_stack[count($page_stack)-1] != $actual ) {
            $null = array_pop($page_stack);
         } // while
         $_SESSION['page_stack'] = $page_stack;
      } // if
      // set script id to last entry in program stack
      $actual = $page_stack[count($page_stack)-1];
      $location = 'http://' .$_SERVER['HTTP_HOST'] .$actual;
      header('Location: ' .$location);
      exit;
   } // if

   ... // continue processing

} // initSession

Предпринятое действие зависит от того, существует ли текущий сценарий в стеке программы или нет.Есть три возможности:

  • Текущий сценарий не находится в массиве $ page_stack, и в этом случае его не разрешается продолжать.Вместо этого он заменяется сценарием, который находится в конце массива.
  • Текущий сценарий находится в массиве $ page_stack, но это не последняя запись.В этом случае все следующие записи в массиве удаляются.
  • Текущий скрипт является последней записью в массиве $ page_stack.Это ожидаемая ситуация.Пьет по всему кругу!
Это было полезно?

Решение

Это хорошее обсуждение, но, более того, вам следует изучить функцию Post Redirect Get (PRG), также известную как «Get after Post».

http://www.theserverside.com/patterns/thread.tss?thread_id=20936

Другие советы

Если вы не поняли мою статью, то вам следует внимательно прочитать Рисунок 1 который описывает типичный сценарий, когда пользователь проходит через ряд экранов — вход в систему, меню, список, поиск, добавление и обновление.Когда я описываю движение ВПЕРЕД, я имею в виду, что текущий экран приостанавливается, пока активируется новый экран.Это происходит, когда пользователь нажимает ссылку на текущем экране.Когда я описываю движение как НАЗАД, я имею в виду, что пользователь завершает текущий экран (нажимая кнопку ВЫХОД или ОТПРАВИТЬ) и возвращается к предыдущему экрану, который возобновляет обработку с того места, где он остановился.Это может включать в себя внесение любых изменений, внесенных в экран, который только что был закрыт.

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

Стек страниц поддерживается двумя функциями:

  • ScriptNext () используется для обработки движения вперед, которое добавляет новую запись в конце стека и активирует новую запись.
  • ScriptPrevious () используется для обработки обратного движения, которое удаляет последнюю запись из стека и повторно активирует предыдущую запись.

Теперь возьмем ситуацию в примере, когда пользователь перешел на страницу 4 экрана СПИСОК, перешел на экран ДОБАВИТЬ, а затем вернулся на страницу 5 экрана СПИСОК.Последним действием на экране «ДОБАВИТЬ» было нажатие кнопки «ОТПРАВИТЬ», которая использовала метод POST для отправки на сервер данных, которые были добавлены в базу данных, после чего процесс автоматически завершился и вернулся на экран «СПИСОК».

Поэтому, если вы нажмете кнопку НАЗАД на странице 5 экрана СПИСОК, история браузера сгенерирует запрос на последнее действие на экране ДОБАВИТЬ, которым была POST.Это допустимый запрос с точки зрения браузера, но не с точки зрения приложения.Как приложение может решить, что запрос недействителен?Проверяя его стек страниц.Когда экран ADD был завершен, его запись была удалена из стека страниц, поэтому любой запрос экрана, которого нет в стеке страниц, всегда можно рассматривать как недействительный.В этом случае неверный запрос может быть перенаправлен на последнюю запись в стеке.

Поэтому ответы на ваши вопросы должны быть очевидными:

  • Вопрос:Где вы вызываете каждую функцию?
  • А:Вы называете функцию scriptNext (), когда пользователь выбирает перемещаться на новом экране и вызовать функцию ScriptPrevious (), когда пользователь завершает текущий экран.
  • Вопрос:Какая функция должна быть названа первой, а какая следующая, а какая третья?
  • А:Каждая функция вызывается в ответ на действие, выбранное пользователем, поэтому одновременно используется только одна функция.
  • Вопрос:Будут ли все функции вызваны во всех файлах в приложении?
  • А:Все функции должны быть доступны во всех файлах в приложении, но вызываются только при выборе пользователем.

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

Часть, которая меня особенно интересует, — это управление кнопкой «Назад», чтобы предотвратить дублирование записей в базе данных при нажатии кнопки «Назад».

Ваша предпосылка неверна.Не существует такого понятия, как «синяя кнопка «Назад», если вы разрабатываете свое приложение как веб-приложение.Если вы разрабатываете свое приложение без какого-либо состояния на стороне сервера, в первом случае вы никогда не столкнетесь с этой проблемой.Этот минималистичный подход к веб-приложениям работает удивительно хорошо и обычно известен как REST.

@троэлскн

Если вы разрабатываете свое приложение без какого-либо состояния на стороне сервера....

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

@Марстон.

Я решил проблему с помощью post/redirect/get, но считаю, что это руководство имеет определенную ценность, и, возможно, Тони Марстон сможет подробно рассказать об этом.И как его можно использовать для решения не обязательно моей конкретной проблемы, но, возможно, чего-то похожего.Или чем это лучше, чем post/redirect/get, если эти функции действительно можно использовать для решения моей конкретной проблемы.Я думаю, что это будет хорошим дополнением к здешнему сообществу.

if ($_POST) {
    process_input($_POST);
    header("Location: $_SERVER[HTTP_REFERER]");
    exit;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top