GD Star Rating
loading...

Народ, я тут себя идиотом ощущаю.
Рассмотрим простую ситуацию: отправка веб-формы с валидацией. Предположим, url, отвечающий за форму, будет /user/create.

Как делаю я:
GET /user/create – отображение формы
POST /user/create – обработка данных и
– либо сохранение данных + редирект на /user/detail/%id%
– либо вывод формы обратно вместе с ошибками валидации

Как делают люди (паттерн PRG):
GET /user/create – отображение формы
POST /user – обработка данных и
– либо сохранение данных + редирект на /user/detail/%id%
– либо сохранение ошибок в сессию + редирект на /user/create + добавление ошибок из сессии к форме

Допустим, на конкретные урлы посрать, restful, там, вот это всё.
Но в паттерне PRG присутствует два неловких момента:
1. лишний запрос (из-за редиректа)
2. протаскивание ошибок через сессию

Профит же (достаточно сомнительный, на мой взгляд) в том, что пользователь, случайно нажав F5, не получит срашное окно “подтвердите повторную отправку формы”.

Поговорим об этом?

PRG, 5.0 out of 5 based on 1 rating
Tagged with →  

18 Responses to PRG

  1. Splmo:

    присоединюсь к вопросу. тоже хочется придумать как это правильно организовать такую вещь

  2. Worer:

    Всегда делал первым (твоим) способом и не переживал на этот счёт.

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

    Так же довольно странным каж-ся кол-во действий, которое необходимо совершить для сираной валидации и вывода сообщений об ошибках. Допустим, у меня несколько бэкендов и сессию я положил куда-нибудь в redis… На каждый submit 1-2 доп. запроса в редис – довольно пугающе.

  3. 01pre:

    Посмотри на форм-фреймворк симфони и прекрати уже пытаться изобрести велосипед, который до тебя умные люди миллион раз изобрели.

  4. HprVelo:

    опиши в двух словах плз.

    Потому что, к примеру, в Yii обработка форм идет по первому методу, в Laravel (где много чего из Симфони утащили) – по второму.

  5. Xuaef:

    Переотправка формы по F5 – это провал для программиста. Хранить флэши в сессии – это оок. Юзай PRG.

  6. 01pre:

    новый объект – /obj/new / редактирование /obj/edit/id/1
    сабмит на /obj/create
    если валидно – /obj/show/id/1
    Если невалидно – остаёмся на /obj/create
    Схема такая. Форма создаётся два раза – на new/edit и на create, только во втором случае на неё биндится реквест и она перестаёт быть пустой. Следовательно, валидация вся проходит на /create/
    Флеши нужно ставить только вроде “Спасибо, вы успешно сохранили объект”

  7. HprVelo:

    речь не только о флешах, но и о пробросе пользовательских данных.

    В первом случае засабмиченные данные рендерятся прямо в форму (если валидатор не пропустил).

    Во втором – сохраняются в сессию, происходит редирект, извлекаются из сессии, рендерятся в форму (иначе форма будет пустая).

    Это ок?

  8. HprVelo:

    ну, похоже на то, как я обычно делаю, да. Только не очень понятен смысл существования двух урлов /new и /create. Один фиг, при невалидной форме на create остаемся.

  9. Xuaef:

    оок. Это тот же флеш. Сериализовал модель, сунул в сессию, редиректнул, десериализовал. Или можно в базу класть, в шаредмем, да хоть куда.

  10. 01pre:

    нашёл кого слушать

  11. 01pre:

    new – это просто пустая форма, без какой бы то ни было модели. Create – процессинг модели. При этом create принимает только POST

  12. X0bef:

    в чем проблема сохранять инфу об ошибки в сессии в первом случае?

    Зацени как всё просто в Yii:

    /www/protected/controllers/UserControlle r.php:

    class UserController extends Controller {
    public function actionCreate() {
    $model = new User(‘create’);
    if(isset($_POST[‘User’])) {
    $model->attributes = $_POST[‘User’];

    if($model->validate() && $model->save()) {
    $this->redirect(‘view’,array(‘id’=>$model->id));
    } else {
    // Это пример как ошибки в сессии сохранить, но в Yii необязательно
    app()->user->setFlash(‘error’, CHtml::errorSummary($model));
    }

    }

    $this->render(‘view’,array(
    ‘model’=>$model,
    ));
    }

    public function actionView($id) {
    $this->render(‘view’,array(
    ‘model’=>$this->findModel(‘User’, $id),
    ));
    }
    }

  13. Xuaef:

    пиздец ебаный.

  14. HprVelo:

    бро, как в Yii – я знаю 🙂

    Речь не о конкретной реализации, а о подходе:

    вывод сразу + мерзкий confirm form resubmit VS протаскивание через хранилище + мерзкий лишний редирект.

  15. Xuaef:

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

  16. Worer:

    Кстати, стоит добавить что перенос формы на XHR позволит убрать назойливое окно ресабмита, а при этом так же избавит от повторного рендеринга страницы с формой. Большая часть современных фрейморков позволяют без особых проблем реализовать ajax-отправку + валидацию формы с результатом валидации в виде, например, json-а. В случае возврата success, делать редирект на client-side с предварительным выводом сообщения об успешном выполнения операции и, например, loading bar-а.

    Да, при всем этом можно оставить обратную совместимость с первым вариантом, если вдруг не работает Ajax o_o

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

  17. AmtSport:

    да, я вот тоже не очень понял, почему бы не использовать ajax.

  18. Xuaef:

    это – лучший вариант, если делать по уму.

Добавить комментарий