【问题标题】:Wrong module is displayed in next page when using $_SESSION使用 $_SESSION 时在下一页显示错误的模块
【发布时间】:2012-11-24 23:40:12
【问题描述】:

下面我有一个 php 脚本,它显示一个“课程”下拉菜单和一个“模块”下拉菜单。假设发生的是用户首先从“课程”下拉菜单中选择一门课程,然后属于所选课程的模块列表将出现在“模块”下拉菜单中。下面是代码:

create_session.php  



$sql = "SELECT CourseId, CourseNo, CourseName FROM Course"; 

$sqlstmt=$mysqli->prepare($sql);

$sqlstmt->execute(); 

$sqlstmt->bind_result($dbCourseId, $dbCourseNo, $dbCourseName);

$courses = array(); // easier if you don't use generic names for data 

$courseHTML = "";  
$courseHTML .= '<select name="courses" id="coursesDrop">'.PHP_EOL; 
$courseHTML .= '<option value="">Please Select</option>'.PHP_EOL;  

while($sqlstmt->fetch()) 
{ 
    $courseno = $dbCourseNo;
    $course = $dbCourseId;
    $coursename = $dbCourseName; 
    $courseHTML .= "<option value='".$course."'>" . $courseno . " - " . $coursename . "</option>".PHP_EOL;  
} 

$courseHTML .= '</select>'; 

?>


<form action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>" method="post">
    <table>
        <tr>
            <th>Course: <?php echo $courseHTML; ?>
                <input id="courseSubmit" type="submit" value="Submit" name="submit" />
            </th>
        </tr>
    </table>
</form>

<?php

if (isset($_POST['submit'])) {

    $submittedCourseId = $_POST['courses'];

    $query = "SELECT cm.CourseId, cm.ModuleId, c.CourseNo, m.ModuleNo,
            c.CourseName,
            m.ModuleName
            FROM Course c
            INNER JOIN Course_Module cm ON c.CourseId = cm.CourseId
            JOIN Module m ON cm.ModuleId = m.ModuleId
            WHERE
            (c.CourseId = ?)
            ORDER BY c.CourseName, m.ModuleId";

    $qrystmt=$mysqli->prepare($query);

    // You only need to call bind_param once
    $qrystmt->bind_param("s",$submittedCourseId);
    // get result and assign variables (prefix with db)

    $qrystmt->execute(); 

    $qrystmt->bind_result($dbCourseId,$dbModuleId,$dbCourseNo,$dbModuleNo,$dbCourseName,$dbModuleName);

    $qrystmt->store_result();

    $num = $qrystmt->num_rows();

    if($num ==0){
        echo "<p style='color: red'>Please Select a Course</p>";
    } else { 

        $dataArray = array();

        while ( $qrystmt->fetch() ) { 
            // data array
            $dataArray[$dbCourseId]['CourseName'] = $dbCourseName; 
            $dataArray[$dbCourseId]['CourseNo'] = $dbCourseNo; 
            $dataArray[$dbCourseId]['Modules'][$dbModuleId]['ModuleName'] = $dbModuleName; 
            $dataArray[$dbCourseId]['Modules'][$dbModuleId]['ModuleNo'] = $dbModuleNo; 

            // session data
            $_SESSION['idcourse'] = $dbCourseNo;
            $_SESSION['namecourse'] = $dbCourseName;
            $_SESSION['idmodule'] = $dbModuleNo;
            $_SESSION['namemodule'] = $dbModuleName;

            }

        foreach ($dataArray as $foundCourse => $courseData) {

            $output = ""; 

            $output .= "<p><strong>Course:</strong> " . $courseData['CourseNo'] .  " - "  . $courseData['CourseName'] . "</p>";

            $moduleHTML = ""; 
            $moduleHTML .= '<select name="module" id="modulesDrop">'.PHP_EOL;
            $moduleHTML .= '<option value="">Please Select</option>'.PHP_EOL;      
            foreach ($courseData['Modules'] as $moduleId => $moduleData) {        

                $moduleHTML .= "<option value='$moduleId'>" . $moduleData['ModuleNo'] . " - " . $moduleData['ModuleName'] ."</option>".PHP_EOL;        
            } 
        }
    $moduleHTML .= '</select>';

    echo $output;

?>

<form action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>" method="post">
    <table>
        <tr>
            <th>Course: <?php echo $moduleHTML; ?>
                <input id="courseSubmit" type="submit" value="Submit" name="submit" />
            </th>
        </tr>
    </table>
</form>

假设我在“课程”下拉菜单中选择课程INFO101 - Information Communication Technology,它会在下面的模块下拉菜单中显示与该课程对应的以下模块:

CHI2520 - Advanced Web Programming
CHI2220 - Systems Strategy
CHI2350 - Interactive Systems

现在这是我遇到的问题。如果我选择模块CHI2520 - Advanced Web Programming 然后访问下面的页面,它会显示这个模块而不是CHI2350 - Interactive Systems

QandATable.php:

    <?php

    if (isset($_POST['idmodule'])) {

        $_SESSION['idmodule'] = $_POST['idmodule'];

    }

    if (isset($_POST['namemodule'])) {

        $_SESSION['namemodule'] = $_POST['namemodule'];

    }

if (isset($_POST['idcourse'])) {

$_SESSION['idcourse'] = $_POST['idcourse'];

}

if (isset($_POST['namecourse'])) {

$_SESSION['namecourse'] = $_POST['namecourse'];

}


    $outputDetails = "";
    $outputDetails .= "
    <table id='sessionDetails' border='1'>
    <tr>
    <th>Course:</th> 
    <th>{$_SESSION['idcourse']}  {$_SESSION['namecourse']}</th>
    </tr>
<tr>
<th>Module:</th> 
<th>{$_SESSION['idmodule']}  {$_SESSION['namemodule']}</th>
</tr>
    </table>
    ";

    echo $outputDetails;

    ?>

我的问题是为什么它在另一页显示错误的模块编号和名称?两个页面都包含session_start();

下面是导航到 QandATable.php 的表单:

<form action="QandATable.php" method="post" id="sessionForm">
            <table><tr><th>6: Module:</th>
            <td><?php echo $moduleHTML; ?></td>
            </tr>
            </table>
            <p><strong>11: </strong><input class="questionBtn" type="submit" value="Prepare Questions" name="prequestion" /></p>   


        </form>

【问题讨论】:

  • 您正在将$dataArray 构建为二维数组,但在每次迭代时将值存储到$_SESSION 中的提取循环中。您的意思是也将它们存储为数组吗?
  • 您发布到QandATable.php 的代码/表单是什么?您正在检查 if (isset($_POST[...])) 以休息 $_SESSION[...],输入您显示的唯一代码/表单是 &lt;form action="&lt;?php echo htmlentities($_SERVER['PHP_SELF']); ?&gt;" method="post"&gt; 并且它仅字段 &lt;select name="courses" id="coursesDrop"&gt;&lt;select name="module" id="modulesDrop"&gt;
  • @MichaelBerkowski 是的,这就是我要说的
  • @sean 我在下拉菜单中包含了仅包含模块列表的表单,然后在问题底部提交给 QandATable.php
  • 您正在检查 isset($_POST['idmodule'])isset($_POST['namemodule']) 以更改您的 $_SESSION['idmodule']$_SESSION['namemodule'],但是您没有任何带有 name="idmodule"name="namemodule" 的表单元素,所以它会始终恢复到预设 $_SESSION['idmodule']$_SESSION['namemodule']$_POST['idmodule'] & $_POST['namemodule'] 哪里来的?

标签: php mysql mysqli


【解决方案1】:

一旦页面已经加载,您就不能分配php sessions!好吧,您可以,但不仅仅是 php 本身!让我解释一下:

  • 第一个请求(表单被下载 - 不显示任何模块)

  • 第二个请求(新表单被下载 - 根据已提交的 courseid 显示正确的模块)

  • 第三个请求(根据提交的模块ID,您必须填充php会话以供以后使用)

您尝试做的是在第二个请求期间填充会话变量...但是,您无法通过这样做来检索正确的模块 ID!只有浏览器和最终的 javascript 知道在页面就在浏览器中的特定时间点选择了什么!

正如我刚才所说,您实际上所做的是在第二个请求中编写您的会话。 这意味着您在用户选择模块之前编写了会话变量!您放入会话的内容只不过是循环中最后获取的结果行!这就是为什么您总是在会话中使用最后一个模块的原因,在您的情况下是 Interactive Systems!

让我们现在找到解决方案

如果您的课程/模块选择器正常工作,一旦用户选择了课程,就会显示正确的模块,您只需提出第三个请求!

<form name="moduleid" [...] >

    <option value="[moduleid]> [moduleno] - [modulename] </option>
    
    [...]
    
</form>

基于这样的结构...我只是猜这就是您的模块表单的样子...您必须向服务器执行第三个请求,该请求可以在同一页面上,就像您为添加模块选择,或另一个! 这里的线索代码类似于下面的代码...您甚至不必生成任何输出;)

if ( isset($_POST['moduleid']) )
{
    $stmt = $mysqli->prepare('select moduleno, modulename from  module where moduleid = ?');
    
    $stmt->bind_param('s', $_POST['moduleid'] );
    
    if ( $stmt->execute() )
    {   
            $stmt->bind_result($moduleno, $modulename); $stmt->fetch();

        $_SESSION['moduleid'] = $_POST['moduleid'];
        $_SESSION['moduleno'] = $moduleno;
        $_SESSION['modulename'] = $modulename;
    }
}

如果您的课程/模块选择器无法正常工作...请参阅我的其他答案;)

【讨论】:

    【解决方案2】:

    我不知道您在此处从原始脚本中遗漏了什么,但您的问题似乎强化了如果没有正确使用会话和发布变量可能会很棘手!这两种方法中的每一种都有一个非常特定的目的as you can read here。对于您提供给我们的信息,post vars 就足够了:)

    在您的脚本中的某个地方,您每次循环循环时都会重新分配会话变量。这意味着只有最后一个“模块”将存储在您的会话中:

    $_SESSION['idcourse'] = $dbCourseNo;
    $_SESSION['namecourse'] = $dbCourseName;
    $_SESSION['idmodule'] = $dbModuleNo;
    $_SESSION['namemodule'] = $dbModuleName;
    

    然而,另一方面,您并没有在此代码中的任何地方使用会话...因此它们可能无用或无关紧要(至少在此页面上)!

    除此之外,你的行动中没有必要做奇怪的事情!

    <form action="" method="post">
    

    做完全一样的事情;)并且不涉及任何php!

    还有什么...问题也可能出在您的查询中,从您的数据库中检索损坏的信息!


    这是一个快速的解决方案

    可能有一些错误...我还没有运行脚本!我没有可用的网络服务器,我的错……但您可能会发现其中的一种方法!它只是为了给你一个想法,因为你真的不需要整个会话开销;)我什至稍微改变了你的第二个查询......你很可能也不需要加入三个表!实际上 course_modulesmodule 为您提供所有需要的信息,前提是您从之前提交的表单中获得 courseid!

    每次只运行第一个查询...加入三个表并不比进行更简单的查询更快..也就是说...这是代码:P 希望对您有所帮助!

    <?php $_courseid = isset($_POST['courseid']) ? $_POST['courseid'] : null; ?>
    
    <!-- action filled only for validation purpose, all browsers will reload the same page by default -->
    
    <form method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>">
    
        <!-- you should be using tables for tabular data only -->
    
        Course: 
    
        <!-- using onchange is user friendly -->
    
        <select name="courseid" id="coursesDrop" onchange="this.form.submit()">
    
        <?php if ( !isset($_courseid) ): ?>
    
            <option selected>Please Select</option>
    
        <?php endif; 
    
        $result = $mysqli->query('select courseid, courseno, coursename from course');
    
        while( list($courseid, $courseno, $coursename) = $result->fetch_array() ): ?>
    
            <option value="<?php echo $courseid ?>" <?php if ($_courseid == $courseid) echo "selected" ?>>
    
                <?php echo "{$courseno} - {$coursename}" ?>
    
            </option>
    
        <?php endwhile; $result->free(); ?> 
    
        </select>            
    
        <?php if ( isset($_courseid) ): ?>
    
        <select name="module" id="modulesDrop">   
    
            <option selected>Please Select</option>         
    
            <?php $stmt = $mysqli->prepare('select m.moduleid, moduleno, modulename form `course_module` join `module` m using(moduleid) where courseid = ? order by m.moduleid');
    
            $stmt->bind_param('s', $_courseid);
    
            $stmt->execute();
    
            $result = $stmt->store_result();
    
            while( list($moduleid, $moduleno, $modulename) = $result->fetch_array() ): ?>
    
                <option value="<?php echo $moduleid ?>"><?php echo "{$moduleno} - {$modulename}" ?></option>
    
            <?php endwhile; $result->free(); $stmt->close(); ?>
    
            </select>
    
        <? endif; ?>
    
    </form> 
    

    【讨论】:

    • 如果你能解决这个问题,我会奖励你赏金,因为我似乎无法弄清楚
    • 我要做的就是在其他 php 脚本 (QandATable.php) 中写什么,以便能够在该页面上显示正确的模块名称和编号,这就是我的全部问。目前,您还没有为 QandATable.php 脚本显示任何内容。请再读一遍问题,你就会明白了:)
    • 没有什么比你在这里写的问题中所问的更多了!模块会根据所选课程进行更新!你的问题没有什么了......它可能已经被编辑了:)
    • 我的错误,它已被编辑,我必须编辑错误的问题,我已执行回滚以再次显示完整的问题。请再次阅读问题:)
    • 好的,让我们再试一次...第一页真的有效吗(我的意思是下拉菜单本身)?如果是这样,只需将我上面写的内容作为优化代码的建议!但是,如果您想在用户选择一个模块后向您的 php 会话写入内容,您必须运行另一个请求才能实际编写会话!
    猜你喜欢
    • 2017-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    • 2015-04-22
    • 1970-01-01
    相关资源
    最近更新 更多