如何创建具有客户端特征的服务器端表单提交脚本


How do I create a server-side form submission script that has client-side characteristics?

我正在PHP中构建一个表单。我知道如何显示表单,然后从$_POST变量中获取提交的值,我知道如何验证这些变量,并根据输入显示"Thank You"或"Error"页面。

我不知道怎么做,虽然,是创建一个类似客户端的系统,其中,尽管我的用户点击"后退"按钮,一个单独的屏幕,然后我可以采取我从第一次提交收集的信息,并显示动态错误消息,如"请提供一个有效的电子邮件地址"或"名字是必填字段"旁边输入错误的字段。我还想检索任何以前提交的有效数据,并将其填充到表单中,这样用户就不会因为丢失他们输入的所有内容而感到沮丧。

在PHP中完成这样的事情的正确方法是什么?我最初认为,如果我可以传回一个带有input type="hidden"标签的错误消息数组,那么我就可以用PHP动态地提取我的值并显示消息,但是我一直被这种方法所困。

您可以在php会话中添加错误,但这会给打开多个浏览器选项卡的用户带来问题。

我的首选方法是将表单提交到同一页面,并将错误直接放在该页上,这样用户就不必单击后退按钮。这样就可以直接在表单中突出显示字段(将背景或轮廓设置为红色或类似的颜色)

<input type="text" 
    <?php (empty($_POST['field']?'style="backgroung-color: red;"':''))?>
    name="field" value="<?php echo $_POST['field']?>" />

您可以输入<input type="text" name="field" value="<?php echo $_POST['field']?>" />以获得旧值。
因为根据定义,网络是无状态的,所以当用户按下后退按钮时,没有真正好的方法来跟踪用户的行为。有一些黑客使用隐藏iframe工作,但这是更麻烦的方式,你正在寻找的

不要把客户端逻辑和服务器逻辑混在一起。完全相同的脚本可以输出表单并接受表单的输入。如果输入成功验证,则继续执行。如果没有,它将再次显示表单,这次显示错误消息和已经输入的数据。

下一次用户提交表单时,再次开始验证,直到成功通过。

因此,您首先使用输入值和错误消息扩展表单,但只有在标记为/set时才显示它们。

这可以通过$_POST旁边的额外变量来完成-或者如果你喜欢它-通过使用一个框架的完整的表单抽象,如zend框架(这可能是你喜欢做的开销)或仅仅使用一个库/组件,如流行的HTML_QuickForm2。

编辑:

这是一些非常简单的代码来演示整个方法,如果您使用库,它会更好(并且您不必编写代码,而是可以专注于实际的形式,如顶部的定义)。这段代码更多的是用于阅读和理解流程,而不是用于使用,我很快地输入了它,所以它(肯定有)语法错误,它的功能不完整,不适合一个完整的表单。这个只有一个电子邮件字段,甚至没有提交按钮:

/* setup the request */
$request->isSubmit = isset($_POST['submit']);
/* define the form */
$form->fields = array
(
    'email' => array
    (
        'validate' => function($value) {return filter_var($value, FILTER_VALIDATE_EMAIL);},
        'output' => function($value, $name) {return sprintf('<input type="text" value="%s" id="%s">', htmlspecialchars($value), htmlspecialchars($name)},
        'default' => 'info@example.com',
    ),
);
/**
 * Import form data from post request
 *
 * @return array data with keys as field names and values as the input strings
 *               or default form values.
 */
function get_form_post_data($form, $request)
{
    $data = array();
    foreach($form->fields as $name => $field)
    {
        $data[$name] = $field->default;
        if ($request->isSubmit && isset($_POST[$name]))
        {
            $data[$name] = $_POST[$name];
        }
    }
    return $data;
}
/**
 * Validate form data
 */
function validate_form_data($form, $data)
{
    foreach($form->fields as $name => $field)
    {
        $value = $data[$name];
        $valid = $field['validate']($value);
        if (!$valid)
        {
            $form->errors[$name] = true;
        }
    }
}
function display_form($form, $data)
{
    foreach($form->fields as $name => $field)
    {
        $value = isset($data[$name]) ? $data[$name] : '';
        $hasError = isset($form->errors[$name]);
        $input = $field['output']($name, $value);
        $mask = '%s';
        if ($hasError)
        {
            $mask = '<div class="error"><div class="message">Please Check:</div>%s</div>';
        }
        printf($mask, $input);
    }
}

// give it a run:
# populate form with default values -or- with submitted values:
$form->data = get_form_post_data($form, $request);
# validate form if there is actually a submit:
if ($request->isSubmit)
{
    validate_form_data($form, $form->data);
}
# finally display the form (that can be within your HTML/template part), works like echo:
display_form($form, $form->data)

使用表单提交到同一页面,如果表单验证,使用标题将用户重定向到感谢页面。

header("Location: thank-you.php");

如果表单验证失败,您可以很容易地在同一页面上显示所有错误。