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

时间:2011-08-04 21:09:58

标签: php validation

我正在使用PHP来构建表单。我知道如何显示表单然后从$ _POST变量中提取值,我知道如何验证这些变量并根据输入显示“谢谢”或“错误”页面。

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

在PHP中完成这样的事情的正确方法是什么?我原本以为如果我可以传回一个带有输入类型=“隐藏”标签的错误消息数组,那么我可以使用PHP动态显示我的值并显示消息,但我一直陷入这种方法。

3 个答案:

答案 0 :(得分:3)

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

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

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

这可以通过$_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)

答案 1 :(得分:3)

您可以在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,但这比你正在寻找的更麻烦。

答案 2 :(得分:0)

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

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

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