【问题标题】:PHP session variables change with file includePHP会话变量随文件包含而变化
【发布时间】:2011-10-13 03:14:21
【问题描述】:

这个问题基于之前的question I asked,但由于我不确定问题可能来自哪里,所以编辑变得很混乱。 (请告知此问题是否需要关闭)

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

感谢 Melsi 的另一个问题,我设法将问题缩小到几行代码。

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

结构是这样的:

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

文件如下:

索引.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>

菜单.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";

?>

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

在我得到的生产服务器上:

-首次加载:Array ([lang] => fr)(默认,正确)

-点击英文链接:Array ( [lang] => Tn )

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

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

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

注意:当我删除 menus.php 中的包含时,问题就消失了

【问题讨论】:

  • 允许偶尔重复,这里的代码与您的第一个问题完全不同。 -- 你应该修复的第一件事是你草率的格式和/或花括号(省略通常是不好的)。目前尚不清楚您的第一个 sn-p 的行为方式。 -- 其次,您的问题可能是 $_SESSION 变量被映射到全局范围。因此$lang['text']= 赋值实际上覆盖了共享会话/全局$lang 变量的第一个[0] 字符。
  • 好吧,收回来,代码看起来很棒。 -- 检查register_globals 是否已启用以及重复中提到的 PHP 5.2.x 中的兼容性标志。如果完全相同的代码在您的开发系统上运行良好,那么它在您的生产服务器上肯定是一个垃圾配置。
  • 查看phpinfo()。或print_r(ini_get_all());。这应该告诉您与 register_globals 和会话错误有关的确切配置。这实际上是您应该与托管服务交谈的少数危险设置之一 - 如果它存在的话。
  • 是的,它应该敲响警钟。 php.net/manual/en/security.globals.php

标签: php session-variables


【解决方案1】:

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

索引.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>

菜单.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;

?>

我认为这会解决您的问题

【讨论】:

    【解决方案2】:

    如果您仔细查看我在上一个问题中的answear,那么提到的第一件事(用粗体字写成)就是这样:

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

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

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

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

    你是这么说的:

    谢谢,但问题不在于我的网站结构

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

    另一方面,面向对象的方法入门难度更大,因为需要学习更多的东西(对象、原型、接口、关系(属于、属于)等),并且需要不同的行为。 但是你肯定会受益更多!

    最后一件事!一个结构良好的站点使会话管理几行,一开始只写一次,仅此而已。

    我很高兴你能解决你的问题!

    【讨论】:

    • 我在您的其他答案中注意到了不同的方法。从头开始重写这个项目是矫枉过正的,但我肯定会在下一个项目中考虑到它,尽管我更喜欢 php 的老派方法,因为它干净且直接(请注意,我的代码可以正常工作并且问题来自生产服务器,如上面的 cmets 中所述)。感谢梅尔西的帮助。
    猜你喜欢
    • 2014-05-18
    • 2012-07-13
    • 1970-01-01
    • 2017-11-22
    • 1970-01-01
    • 1970-01-01
    • 2019-10-20
    • 1970-01-01
    • 2017-12-17
    相关资源
    最近更新 更多