PHP+MySQL网站(localhost)与netbeans xdebug一起工作,但不是唯一的


PHP+MySQL website (localhost) working with netbeans xdebug, but NOT ALONE

好吧,这听起来可能偏离主题,但我想知道是否有人有过类似的经历,以及他们是否找到了问题/解决方案。

很抱歉,这篇帖子变得更像是自我尝试和错误拼写,因为没有人回答。我在问题的底部添加了问题解决的状态更新

有一段时间,问题似乎是我的数据库更新查询

我正在netbeans7.3.+上开发PHP+MySQL网站示例。一切都很好。否我的登录表单(假设保存一些$_SESSION变量并重定向到页面)突然不工作

奇怪的是,当我使用Netbeans+Xdebug进行调试时,一切都很好。会话变量设置正确,页面转发正确。

问题:是否有人面临类似的问题?有人知道可能出了什么问题吗

我只能假设当我运行xdebug时,系统中的某些内容设置不同。(但几天前,完全相同的登录运行良好)。

我尝试了很多事情(很多很多小时,但大多数现在都没有出现在我的脑海中)。我试图在远程服务器上移动页面,但同样的行为仍在继续。

(如果你想了解更多信息,我会编辑。)

希望有人有想法!

编辑:我认为这与我的php会话变量有关。我意识到,当Xdebug网站以空的php会话变量开始时,它确实使用/获得了与正常情况下相同的变量(?)

代码正在创建到数据库的会话,但没有进入下一步来设置php会话变量。(查看index.php中标记为/*此处为该地点*/的位置

好的。这里是STRIPPED代码(使用netbeans+xdebug,而不是单独使用):

index.php:

<?php
//Open PDO connection to MySQL server: $db_con 
$db_connection = $_SERVER['DOCUMENT_ROOT'] . '/test-login/db.php';
require $db_connection;
session_start();
//******************************************************************************
//Helping functions
function convert_time_to_utc_date ($UNIX_timestamp) {
    return gmdate("Y-m-d H:i:s", $UNIX_timestamp);
}
//******************************************************************************
// Function to authenticate user with username and password. returns FALSE if not authenticated and TRUE if successful authentication
function authenticate_username_password($db_con, $usernm, $passwd)
{
    try {
        $stmt = $db_con->prepare("SELECT id, hashed_pwd, COUNT(*) AS usercount FROM gui_users WHERE username=? AND not_in_use = 0 AND deleted = 0");
        $stmt->execute(array($usernm));
        if($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            if($row['usercount'] == 1){
                if(crypt($passwd, $row['hashed_pwd']) == $row['hashed_pwd']){
                    $user_id = $row['id'];                        
                    session_regenerate_id(true);
                    $new_session_id = session_id();
                    $remote = true;
                    $datenow = convert_time_to_utc_date(time());
                    $stmt = $db_con->prepare("INSERT INTO gui_sessions (session_id,user_id,starttime_UTC,lastused_UTC,remote) VALUES (?, ?, ?, ?, ?)");
                    $stmt->execute(array($new_session_id, $user_id, $datenow, $datenow, $remote));
                    return $user_id;
                }            
            }
        }
        return FALSE;
    } catch (PDOException $e) {
        return FALSE;
    }
}
//******************************************************************************
//Function to get user roles
function get_user_roles(PDO $db_con, $user_id)
{
    try {
        $stmt = $db_con->prepare("SELECT role_id, role_last FROM gui_users WHERE id = ?");
        $stmt->execute(array($user_id));
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        return array('max_role_id' => $row['role_id'], 'last_role_id' => $row['role_last']);
    } catch (PDOException $e) {
        return FALSE;
    }
}
//******************************************************************************
// Function to handel sessions, log in and log out
function authenticate(PDO $db_con) {
    //********************
    // If action is LOG IN
    if (isset($_POST['action']) and $_POST['action'] == 'login') {
        if (!isset($_POST['username']) or $_POST['username'] == '' or !isset($_POST['passwd']) or $_POST['passwd'] == '') {
            $GLOBALS['loginError'] = 'Please fill in both fields';
            return FALSE;
        }
        $user_id = authenticate_username_password($db_con, $_POST['username'], $_POST['passwd']);

        if ($user_id !== false && $user_id > 0) {
            $_SESSION['reloadcounter'] = 1;
            $_SESSION['username'] = $_POST['username'];
            $_SESSION['user_id'] = $user_id;
            $_SESSION['user_def_page'] = 1; //get_user_default_page($db_con, $user_id);
            $user_roles = get_user_roles($db_con, $user_id);
            $_SESSION['max_role_id'] = $user_roles['max_role_id'];
            $_SESSION['sel_role_id'] = $user_roles['last_role_id'];
            $goto = isset($_POST['goto']) ? $_POST['goto'] : HTTPS_SERVER;
            header('Location: ' . $goto);
            exit;
        } else {
            $GLOBALS['loginError'] = 'Wrong username or password!';
            return FALSE;
        }
    }
    //*********************
    // If action is LOG OUT
    if (isset($_POST['action']) and $_POST['action'] == 'logout') {
        $user_ses_id = session_id();
        try {
            $stmt = $db_con->prepare("DELETE FROM gui_sessions WHERE session_id=?");
            $stmt->execute(array($user_ses_id));
        } catch (PDOException $e) {
            log_error('PDO_CONN', $e->getCode(), $e->getMessage(), TRUE, $db_con);
        }
        session_regenerate_id(true);
        unset($_SESSION['reloadcounter']);
        unset($_SESSION['username']);
        unset($_SESSION['user_id']);
        unset($_SESSION['user_def_page']);
        unset($_SESSION['max_role_id']);
        unset($_SESSION['sel_role_id']);
        $goto = isset($_POST['goto']) ? $_POST['goto'] : HTTPS_SERVER;
        header('Location: ' . $goto);
        exit;
    }
    //************************************
    // If no action see if user logged in
    $user_ses_id = session_id();
    $datenow = convert_time_to_utc_date(time());
    try {
        $stmt = $db_con->prepare("UPDATE gui_sessions SET lastused_UTC=? WHERE session_id=?");
        $stmt->execute(array($datenow, $user_ses_id));
        if ($stmt->rowCount() == 1) {
            return TRUE;
        } else {
            unset($_SESSION['reloadcounter']);
            unset($_SESSION['username']);
            unset($_SESSION['user_id']);
            unset($_SESSION['user_def_page']);
            unset($_SESSION['max_role_id']);
            unset($_SESSION['sel_role_id']);
            return FALSE;
       }
    } catch (PDOException $e) {
        log_error('PDO_CONN', $e->getCode(), $e->getMessage(), TRUE, $db_con);
        if (DEBUG_ON) {
            echo 'SESSION UPDATE FAILED<br>';
        }
        return FALSE;
    }
}
//******************************************************************************
//SESSION CONTROL
if (!authenticate($db_con)) {
    include 'login.html.php';
    exit();
}
include 'page.html.php';
?>

login.html.hp:

<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <p class="login-error"><?php if(isset($loginError)) { echo $loginError; } else { echo '&nbsp;'; } ?></p>
        <form id="login" action="" method="POST" name="login">
            <label for="username">Username:</label><br />
            <input name="username" type="text" size="40" value="" tabindex="0" /><br />
            <label for="passwd">Password:</label><br />
            <input name="passwd" type="password" size="40" value="" tabindex="1" /><br />
            <input type="hidden" name="goto" value="https://localhost/test-login/"/>
            <input type="hidden" name="action" value="login"/>
            <input type="submit" class="button login" value="Login" tabindex="2"/><br />
        </form>
        <div><?php echo '<pre>' . var_dump($_SESSION) . '</pre>'; ?></div>
    </body>
</html>

page.html.php:

<html>
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <div>
            <h1>Hello world!</h1>
            <?php echo '<pre>' . var_dump($_SESSION) . '</pre>'; ?>
        </div>
    </body>
</html>

编辑:我已经更多地跟踪了这个错误,虽然Xdebug$_POST变量似乎还可以,但独立的PHP解释器正在失去一些方法。

奇怪的是,我在if(isset($_POST['action'])&amp$_POST['action']=='login'),php似乎没有进入其中,但它能够在if子句中插入数据库中的会话。

编辑:刹车直到非常平静帮助我发现了一个大错误,这个错误仍然不应该影响实际问题,但让它更难找到。

因为我忘记在authenticate结束时向if-else添加大括号,所以函数总是取消设置会话变量。一开始,我认为函数无法设置它们,但在重定向到"$_SERVER['HP_SELF']"后,它实际上取消了设置。无论如何,如果UPDATE guid_session语句可以工作,就不应该发生这种情况。但这让我们更难发现问题出在哪里。以下是对index.php的更正:

//************************************
// If no action see if user logged in
$user_ses_id = session_id();
$datenow = convert_time_to_utc_date(time());
try {
    $stmt = $db_con->prepare("UPDATE gui_sessions SET lastused_UTC=? WHERE session_id=?");
    $stmt->execute(array($datenow, $user_ses_id));
    if ($stmt->rowCount() == 1) {
        return TRUE;
    } else {
        unset($_SESSION['reloadcounter']);
        unset($_SESSION['username']);
        unset($_SESSION['user_id']);
        unset($_SESSION['user_def_page']);
        unset($_SESSION['max_role_id']);
        unset($_SESSION['sel_role_id']);
        return FALSE;
    }
} catch (PDOException $e) {
    log_error('PDO_CONN', $e->getCode(), $e->getMessage(), TRUE, $db_con);
    if (DEBUG_ON) {
        echo 'SESSION UPDATE FAILED<br>';
    }
    return FALSE;
}

问题是此更新失败。但我不知道为什么。

$stmt = $db_con->prepare("UPDATE gui_sessions SET lastused_UTC=? WHERE session_id=?");
$stmt->execute(array($datenow, $user_ses_id));
if ($stmt->rowCount() == 1) {
    return TRUE;
}

如果我在php-myadmin:中尝试

UPDATE gui_sessions 
SET lastused_UTC='2013-08-04 12:00:00' 
WHERE session_id='03dfgpiu1jl8idcjf191hqv4m2'

它影响0行,但如果我这样做:

SELECT * 
FROM gui_sessions
WHERE session_id='03dfgpiu1jl8idcjf191hqv4m2'

它返回1行

好的。问题解决了。如果有人遇到类似的问题,我会把答案留在这里。我仍然不知道Xdebug是如何隐藏这个问题的。

问题是我试图通过更新数据库会话表中的last_used字段来验证用户。我假设若查询能够更新那个字段,那个么会话必须是有效的。所以我检查sqlupdatelast_user受影响的行是否等于1,那么用户php会话id是否在会话表中。问题是,如果字段已经具有更新为"reference"的值,MySQL将返回0个受影响的行。在我的情况下,这当然是真的,因为会话last_update字段只是在登录过程中创建的。

但发现这个问题非常痛苦,因为Xdebug在那里做了一些非常奇怪的事情,在0行影响更新查询后,它跳出了函数,而没有转到if子句的else语句,在那里我检查受影响的行数是否等于1。

如果您知道Xdebug为什么会这样做,请发表评论。