我如何从php验证脚本重定向回一个表单,在前端控制器


how do I redirect back to a form from a php validation script, within a front controller

我读过许多关于在执行服务器端验证(假设表单有错误)并显示错误后重定向回表单的问题,但我没有发现任何与我的特定问题相关的问题。我有一个简单的前端控制器,使用。htaccess重定向http请求到index.php。这就是设置;这是我的情况:

register.php是一个发送到validate_registration.php的注册表单。我有代码的形式,显示php变量(这不会被设置,除非验证脚本已经运行)。我在validate_registration.php:

末尾使用它
header("Location: http://www.example.com/register.php");

不幸的是,在register.php中显示错误的代码根本不做任何事情。这是迷失在我的前控制器吗?我的。htaccess代码如下:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond $1 !^(index'.php|ajax|css|error|form|img|js|robots'.txt|securimage|submit)
RewriteRule ^(.*)$ index.php?url=$1 [PT,L]
</IfModule>

和我的前端控制器是这样的(大多数情况下,它是极其简单的switch语句,因为我绝对不需要任何更复杂的,可扩展的,等等):

$url = $_GET['url'];
require_once("header.php");
echo '<body>';
require_once("banner.php");
require_once("navigation.php");
require_once("login_bar.php");
echo '<div id="main">';
switch ($url) {
    case('register.php'):
       require_once('register.php');
       break;
    default:
        require_once('error404.php');
        break;
}
echo '</div>'; //Closing div tag for the id="main" section
require_once("$template_directory/general/footer.php");
echo '</body>';

抱歉,这个问题太长了;我好像修不了了!Validate_registration.php重定向到register.php很好,但变量似乎没有通过前端控制器。此外,这个表单需要在不启用Javascript的情况下工作,因此不幸的是,AJAX不是一个选项。

编辑:下面是带有错误消息的表单的代码;现在还很简单,因为我只是在测试。

<?php
$allowed_fields = array("reg_username",
    "reg_password",
    "reg_confirm_password",
    "reg_email",
    "reg_confirm_email",
    "captcha_code",
    "reg_disclaimer",
);
$db_select_connection = DB::get_admin_connection();
$errors = array();
foreach ($_POST as $key => $value) {
    if (in_array($key, $allowed_fields)) {
        $$key = mysql_real_escape_string($value);
        if ($value == "") {
            $errors["$key" . "_blank"] = "The $key field is required.";
        }
    }
}
// Validation section
// Username
if (ctype_alnum($reg_username)) {
    $errors["reg_username_invalid"] = "Username can only contain letters and numbers.";
}
// Password
if (strlen($reg_password) < 6) {
    $errors["reg_password_short"] = "Password must be at least 6 characters long.";
}
if ($reg_password !== $reg_confirm_password) {
    $errors["reg_password_match"] = "Passwords do not match.";
}
$legal_characters = preg_quote("~!@#$%^&*()");
$trimmed_password = preg_replace("/[^a-zA-Z$legal_characters]/", "", $reg_password);
if ($trimmed_password !== $reg_password) {
    $errors["reg_pass_chars"] = "Password can only contain letters, numbers, and " .      htmlentities($legal_characters, ENT_QUOTES, 'UTF-8');
}
// Email
if ($reg_email !== $reg_confirm_email) {
    $errors["reg_email_match"] = "Email addresses do not match.";
}
if (!Email::validate_email($reg_email)) {
    $errors["reg_email_invalid"] = "Email address is invalid.";
}
//Disclaimer check box
if ($reg_disclaimer !== "on") {
    $errors["reg_disclaimer_accept"] = "You must read and accept the disclaimer to     create an account.";
}

require("http://www.example.com/register.php");
?>

表单的代码只包含两个类似的代码块,用于显示错误。这里涉及到很多格式和样式设置,所以我不会在整个表单上浪费空间。

编辑:另外,我如何格式化的东西作为代码,而不手动把4个空格在前面每行?我直接从Netbeans(我的IDE)复制代码到编辑窗口,高亮显示它,并按下代码,但它仍然不允许我提交我的文章。

如果重定向,将丢失所有表单数据,因为这是一个新请求。相反,如果要显示错误,则在当前请求中呈现表单,并在成功时重定向。

重定向通常用于在表单操作成功完成时防止表单重新发送。

编辑(在评论中进行了大量修改后):

您可能需要重新设计脚本的运行方式。实际上没有要求index.php呈现任何内容,或者您的url总是以.php结尾。

我将建议一种编写应用程序的方法;这可能不是最好的方法,所以请考虑其他方法,但它可能有助于你思考。

    // index.php
    switch($_REQUEST['url']) {
        case('register'):
            $page['controller'] = 'register';
            break
        /* other stuff */
    }
    include_once('controllers/'.$page['controller'].'.php');

    // controllers/register.php
    if($_POST['register_form']) {
        // logic to deal with the form, error messages etc
    }
    $page['title'] = 'Register Now!';
    $page['template'] = 'register';
    include_once('../views/layout.php');

    // views/layout.php
    <!DOCTYPE html>
    <html>
    <head>
    <title><?=$page['title'];?></title>
    </head>
    <body>
    <?php
      // headers and such
      include_once($page['template'].'.php');
      // footers and such
    ?>
    </body>
    </html>

    // views/register.php
    /* your form html */

在这里,你的路由器、控制器逻辑和你的布局和视图模板被分离到具有明确职责的可管理部分。这样,你就不必在应用程序的任何地方重复编写代码。

尝试替换

header("Location: http://www.example.com/register.php");

return require '/path/to/register.php';

设置location header告诉浏览器直接指向register.php。可以把它想象成打开一个新窗口,然后转到register.php。您的post变量都不会执行,因为它们被发送到validate_registration.php,然后validate_registration.php只是将浏览器重定向回register.php。这就是数据丢失的地方。在位置重定向中没有传输任何内容(请记住,HTTP是无状态的。它不会记住,除非被告知(因此是POST,或cookie)。

您需要require('/path/to/register.php');(如Francesco所建议的),以便register.php可以访问这些变量,或者将它们扔到SESSION变量中,并以这种方式从register.php访问它们(请记住,您将需要使用会话集函数)。