как получить ответ на действие формы без ajax в хорошем смысле?

Я знаю, как получить ответ AJAX:

$.post( '/action', 
        { actiontodo: 'insert' } 
        function (data) { alert(data); } );

Внутри action.php (на стороне сервера):

<?php 
       if ($_POST['actiontodo'] == 'insert') 
       { 
           doInsertAction(); 
           echo "inserted"; 
       } 
?>

Наконец, результатом этого кода является предупреждение BOX со словом: вставлено.

НО без ajax у меня есть два способа решить эту проблему (на стороне сервера):

ОДИН:

<?php 

if ($_POST['actiontodo'] == 'insert') { 
    doInsertAction(); 
    header( "Location: " . $_SERVER['HTTP_REFERER'] . " &response=inserted"  ); 
} ?>

ДВА:

<?php
session_start();
if ($_POST['actiontodo'] == 'insert') {
    doInsertAction();
    $_SESSION['response'] = 'inserted';
}
header( "Location: " . $_SERVER['HTTP_REFERER'] );
?>

Возвращаясь на страницу, я получаю ответ от SESSION или от GET и показываю предупреждение.

Мне больше нравится ОДНО решение, но у каждого решения есть проблема:

ОДНА проблема:

Возвращаемый URL: http://www.foo.com/myrefererurl&response=inserted.

Если вы введете этот URL-адрес, не используя форму, вы будете видеть окно предупреждения каждый раз, когда будете обновлять страницу. Вопрос: Как показать сообщение только ОДИН раз? (ТОЛЬКО ПОСЛЕ ДЕЙСТВИЯ ФОРМЫ)

ДВА ПРОБЛЕМЫ:

В SESSION теперь вставлено значение ($_SESSION['response']), когда страница возвращается из действия, очевидно, решение может удалить это значение сеанса, например: unset($_SESSION['response'], но ПРЕДПОЛАГАЕМ, что UNSET не достигнуто по какой-либо причине (сбой соединения или навигация остановлена ​​пользователем и т. д.), когда вы переходите к другой форме на другой странице, отображается предупреждение, поскольку $_SESSION['response'] все еще существует (в другой форме без отправки и не имеет ничего общего с этим ответом).

Я надеюсь, что вы понимаете эти вопросы и предлагаете ЛУЧШЕЕ решение. В основном вопрос в том, как контролировать эти ответы......


person CRISHK Corporation    schedule 04.10.2010    source источник
comment
Во-первых, вы не можете полагаться на $_SERVER['HTTP_REFERER'], вы должны опубликовать имя страницы или что-то еще, чтобы идентифицировать ее и использовать это значение для перенаправления. Лично я выберу второе решение: вы можете unset использовать однажды использованную переменную, и у нее не должно быть никаких причин не быть unset   -  person Shikiryu    schedule 04.10.2010
comment
можете ли вы уточнить, почему вы избегаете AJAX? Вы говорите, что знаете, как это сделать в ajax, но не говорите, почему ищете альтернативу.   -  person Yevgeny Simkin    schedule 04.10.2010
comment
потому что я хочу, чтобы доступ к системе был из любого браузера, даже если у вас нет Javascript... :)   -  person CRISHK Corporation    schedule 04.10.2010
comment
Вы пытаетесь избежать загрузки новой страницы? Почему бы просто не использовать простой, старомодный запрос POST на уровне страницы? Кроме того, Location:xyz.com указывает браузеру перейти по указанному URL-адресу, а не серверу. Откройте Firebug и просмотрите сетевой трафик с включенным Persist, чтобы увидеть его в действии. Вы хотите не полагаться на него в своей бизнес-логике, за исключением случаев, когда целевая страница является фактической конечной точкой вашего приложения.   -  person Andrew    schedule 04.10.2010
comment
@Cris, если это так, не начинайте с AJAX и не стройте внутрь, начните со старомодного HTML, заставьте его работать для всего, что вы считаете своей базовой линией, а затем добавьте поведение AJAX впоследствии. Найдите ненавязчивый AJAX или прогрессивное улучшение.   -  person Andrew    schedule 04.10.2010
comment
Это я делаю, я показываю AJAX в качестве примера ЛУЧШЕГО РЕШЕНИЯ... потому что AJAX делает то, что я хочу делать со СТАРОЙ МОДНОЙ HTML, как вы говорите..   -  person CRISHK Corporation    schedule 04.10.2010


Ответы (1)


Ненавязчивый JS или «прогрессивное улучшение» — это то, что нужно.

Шаг 1:

Сначала создайте свою страницу, чтобы она работала без JavaScript. Допустим, у вас есть простое приложение, в котором пользователь что-то выбирает и нажимает «Отправить». В зависимости от выбора вы либо отобразите полезное сообщение об ошибке над формой, либо обновите страницу с правильным выводом и скроете (или избавитесь) от формы. Создайте эту страницу так же, как для AJAX, но пока ничего не записывайте.

Вот ваша страница:

<html>
<head>
    <style type="text/css">
        p#feedback { display:none;}
    </style>
</head>
<body>
    <div id="feedback"></div>
    <div id="form">
        <form action="getaction.php" method="post" id="actionform">
            <select name="requestedAction">
                <option value="foo">Do Foo</option>
                <option value="bar">Do Bar</option>
            </select>
            <input type="submit">
        </form>
    </div>
</body>
</html>

При успешной подаче. сервер получит запрос с одним значением $_POST: requestedAction=foo (или bar). На основе этого ваш серверный скрипт создаст новую страницу со всем от <html> до </html>.

На данный момент у вас есть страница, которая работает в любом браузере без поддержки JS. Старомодный. Очень надежный.

Шаг 2

Добавьте сценарий, чтобы переопределить поведение submit по умолчанию. Возьмите необходимые данные со страницы и создайте представление AJAX. Единственная разница между этим и приведенным выше представлением заключается в том, что вы добавите флаг, сообщающий серверу, что запрос поступает через AJAX, и отправлять обратно только необходимое сообщение (вы также можете отправить его в другой скрипт). Сценарий сервера в основном будет выполнять ту же логику, что и выше, но вместо того, чтобы создавать всю страницу, он только отправляет строку сообщения и предоставляет AJAX поместить эти данные в нужное место. Ваш ответ может быть просто текстовым фрагментом, блоком HTML или структурой данных XML. Это зависит от ваших потребностей.

<script type="text/javascript">
    $(enhance); // at onDOMReady, run the enhance function

    function enhance() {
        // Override the default form submission behavior:
        $('form#actionform').bind('submit',doSubmit);
    };
    function doSubmit(event) {
        $.ajax(
            {
                type:'POST',
                url:'/path/to/getaction.php',
                data:'request=' + $('form#actionform select[name=requestedAction]').val() + '&type=ajax',
                success:fnCallback
            }   
        );
        // Kill the submit action so the user doesn't leave the page
        event.preventDefault();
    };
    function fnCallback(xhr) {
        var strResponse = xhr.responseText; 
        if (strResponse === "error") {
            $('div#feedback').text("There was an error. Please try again.");
        }
        else {
            $('div#feedback').text(strResponse);
            $('div#form').hide();
        }
    };
</script>

В этом случае отправка AJAX будет идентифицируема сервером, потому что есть второй параметр POST type=ajax.

Сайт, который делает это действительно невероятно хорошо в очень больших масштабах, — это ESPN. Выключите JS и посмотрите заголовки их основных статей под общей картинкой. Поведение идентично их странице с поддержкой AJAX, и, кроме того, что видео не работает, вы действительно никогда не узнаете, включен ли ваш JS или выключен. По сути, невозможно создать такой сайт, не начав с глупого HTML и не нарастив его.

person Andrew    schedule 04.10.2010
comment
Когда вы говорите: «Основываясь на этом», ваш серверный скрипт создаст новую страницу со всем от ‹html› до ‹/html›. Я думаю, это окончательное решение, НО: Что происходит с URL-адресом, я не хочу, чтобы новый URL-адрес был /getaction.php, это означает, что нам нужно указать действие вида: action=‹ ?php эхо selfUrl(); ?›, где selfUrl возвращает текущий URL страницы (включая параметры) и в верхней части скрипта обрабатывает действие В СЛУЧАЕ запроса... . Вы согласны с этим? - person CRISHK Corporation; 04.10.2010
comment
У меня возникают новые проблемы с этим решением, когда пользователь обновляет страницу, получает сообщение для подтверждения, повторно ли отправить форму или нет.... потому что это тот же URL-адрес... - person CRISHK Corporation; 04.10.2010
comment
Что касается двойной публикации, это очень старая проблема. Для этого есть простое решение: на странице формы добавьте скрытый ввод, который либо имеет токен сеанса (если ваш сервер разрешает сеансы), отметку времени, GUID или какой-либо другой уникальный идентификатор. Если ваш сервер поддерживает токены, вы можете просто сравнить их и убить второй запрос. Или вы можете сохранить уникальный идентификатор вместе с данными отправки пользователя и проверить, существует ли уже этот номер. Это дополнительный удар по БД/файловой системе, но именно так вы это делаете. - person Andrew; 04.10.2010
comment
Если вам действительно нужно перенаправить пользователя на другой URL-адрес (что является очень распространенным решением), используйте перенаправление Location:. В этом нет ничего плохого. Я лично пишу свои приложения (или те, которые взаимодействуют с пользователем), чтобы все запросы проходили через один единственный URL-адрес (например, «index.php»), и я никогда не использую параметры URL-адреса. Я считаю, что гораздо проще справляться с безопасностью, поэтому я действительно не делаю этого по-другому. - person Andrew; 04.10.2010