PHP会话变量随文件包含而改变


PHP session variables change with file include

这个问题是基于我之前问过的一个问题,但由于我不确定问题可能来自何处,因此编辑变得混乱。(请告知这个问题是否需要结束)

我在开发环境+ Apache 2上使用PHP 5.3.3开发(我的代码在那里工作)生产服务器有PHP 5.2.6和相同的服务器(相同的代码在这里不起作用)

感谢Melsi在另一个问题上,我成功地将问题缩小到几行代码。

问题是:在一个包含文件中,我启动一个会话并检查变量。根据会话变量,我包含一个语言文件。

结构如下:

-index.php
INCLUDE
    -menus.php
    -lang_fr.php
    -lang_en.php

文件如下:

index . php

<?php
    //SET LANGUAGE
    if (isset($_GET['lang']) && $_GET['lang'] == 'fr') {
        $_SESSION['lang'] = 'fr';
    }
    else if (isset($_GET['lang']) && $_GET['lang'] == 'en') {
        $_SESSION['lang'] = 'en';
    }
    else {
        $_SESSION['lang'] = 'en';
    }
    include_once 'include/menus.php';
?>
<html>
<head>
    <title>building...</title>
</head>
<body>
    <?php
            echo($links);
    ?>
<br><br>
print_r($_SESSION);
<br><br>
    <?php
            print_r($_SESSION);
    ?>
</body>
</html>

MENUS.PHP

<?php
    session_start();
    if(isset($_SESSION['lang']) && $_SESSION['lang'] == 'en') {
        include_once('lang_en.php');
    }
    else if(isset($_SESSION['lang']) && $_SESSION['lang'] == 'fr') {
        include_once('lang_fr.php');
    }
    else {
        $_SESSION['lang'] = 'fr';
        include_once('lang_fr.php');
    }
    $links = <<<EOT
    <a href="/index.php?lang=en">English</a>&nbsp;&nbsp;
    <a href="/index.php?lang=fr">French</a>
EOT;
?>

LAN_EN和FR.PHP

<?php
$lang['test'] = "Test";
?>

这在我的本地服务器上工作,并显示正确的会话变量,当我点击链接。

在生产服务器上我得到:

首次加载:数组((lang) => fr) (默认情况下,正确的)

点击英文链接:数组((lang) => Tn)

-点击法语链接:Array ([lang] => Tr)

如果我在语言文件'Test'更改为'Pest',上面的结果是'Pn'和'Pr'

我想知道代码或配置生产服务器是否有问题(根据他们的支持没有任何问题),如果是这样,可能是什么问题。

注意:当我删除menu .php
中的include时,问题就消失了。

您的代码中的问题是,您设置设置变量和Index.php,但在Menu.php文件中启动会话。请修改为:

index . php

<?php
    ob_start();
    session_start();
    //SET LANGUAGE
    if (isset($_GET['lang']) && $_GET['lang'] == 'fr') {
        $_SESSION['lang'] = 'fr';
    }
    else if (isset($_GET['lang']) && $_GET['lang'] == 'en') {
        $_SESSION['lang'] = 'en';
    }
    else {
        $_SESSION['lang'] = 'en';
    }
    include_once 'include/menus.php';
?>
<html>
<head>
    <title>building...</title>
</head>
<body>
    <?php
            echo($links);
    ?>
<br><br>
print_r($_SESSION);
<br><br>
    <?php
            print_r($_SESSION);
    ?>
</body>
</html>

MENUS.PHP

<?php
    if(isset($_SESSION['lang']) && $_SESSION['lang'] == 'en') {
        include_once('lang_en.php');
    }
    else if(isset($_SESSION['lang']) && $_SESSION['lang'] == 'fr') {
        include_once('lang_fr.php');
    }
    else {
        $_SESSION['lang'] = 'fr';
        include_once('lang_fr.php');
    }
    $links = <<<EOT
    <a href="/index.php?lang=en">English</a>&nbsp;&nbsp;
    <a href="/index.php?lang=fr">French</a>
EOT;
?>

我想这会解决你的问题

如果你仔细看我对你上一个问题的回答,你会发现我提到的第一件事(用粗体写的)就是:

也许会话是从包含的文件启动的,这不应该发生!

Vineet是正确的,我将进一步扩展他的正确答案!

当您将文件child.php包含到father.php中时,您必须将child.php中的代码视为father.php的一部分,您在father.php脚本(如index.php)中所做的第一件事是会话启动。不要在包含的脚本中启动会话,因为这可能会产生一些冲突,因为其他会话可能已经启动。

如果您有许多文件,(更糟糕的是,如果其中一些文件都包含或直接执行,因为没有单个入口点),那么管理所有这些文件有多容易?!

你说:

谢谢,但问题不是来自我的网站结构

这可能不完全正确!问题是,编写老派代码(没有mvc,没有单一入口点,不是真正的面向对象)的好处是,学习曲线非常容易。然而虽然这样的代码很容易写,但这样的代码需要更多的技能来避免错误!

另一方面,面向对象的方法有更多的困难开始,因为有更多的东西要学习(对象,原型,接口,关系(属于,是一部分)等),需要不同的行为。然而你肯定会受益更多!

最后一件事!一个结构良好的网站可以让会话管理变成几行,在开始时只写一次,仅此而已。

我很高兴你正在解决你的问题!