【问题标题】:Sessions not working in localhost but work in live server (Codeigniter)会话不在本地主机中工作,但在实时服务器中工作(Codeigniter)
【发布时间】:2018-03-02 13:44:40
【问题描述】:

我从昨天开始就遇到了这个问题,但我无法解决这个问题。问题是会话在本地环境中不起作用,但是当出于测试目的我将相同的文件放在实时服务器上时,它们都可以正常工作。

如果我的 config.php 文件在这里:

$config['sess_driver'] = 'files';
$config['sess_cookie_name'] = 'ci_session';
$config['sess_expiration'] = 7200;
$config['sess_save_path'] = 'ci_sessions';
$config['sess_match_ip'] = FALSE;
$config['sess_time_to_update'] = 300;
$config['sess_regenerate_destroy'] = FALSE;

$config['cookie_prefix']    = '';
$config['cookie_domain']    = '';
$config['cookie_path']      = '/';
$config['cookie_secure']    = FALSE;
$config['cookie_httponly']  = FALSE;

这是我将数据保存在我的模型文件之一中的方法

$this->session->set_userdata('user',$result); //$result works fine, it produces
right result

在我看来,我试图通过以下方式访问它:

$this->session->userdata['user']['name']; //name here is an element in result array

我收到此错误:

严重性:通知

消息:未定义索引:用户

文件名:home/home.php

行号:2

令我惊讶的是,同样的代码在服务器上运行时没有任何错误。

另外,为了能够知道 Codeigniter 会话保存的数据,我尝试了数据库方法。

我在 config.php 文件中将代码更改为以下

$config['sess_driver'] = 'database';
$config['sess_cookie_name'] = 'ci_sessions';
$config['sess_expiration'] = 7200;
$config['sess_save_path'] = 'ci_sessions';
$config['sess_match_ip'] = FALSE;
$config['sess_time_to_update'] = 300;

它不是插入一行数据,而是插入四行。请看下面的数据库截图(最后四行)。

谁能指出错误?任何帮助将不胜感激。

【问题讨论】:

  • 添加调试行 print_r($this->session->userdata); 并查看会话中的确切内容
  • 这里是输出:Array ( [__ci_last_regenerate] => 1505985569 )
  • 您的本地数据库与您的生产数据库完全相同吗?这些表是相同的名称等?
  • 没错,只是因为它在本地不工作,我试着把它放到网上用相同的数据库和文件验证,它在那里工作
  • 尝试 print_r($this->ci->session->userdata())。还要查看浏览器是否接受来自本地域的 cookie,因为浏览器有时不接受。如果可能的话,给你的机器一个带点的主机名。

标签: php codeigniter session


【解决方案1】:

我做了大量的研发工作,但问题没有解决,但突然我检查了我的 MySQL 版本,当我更改我的 SQL 版本时,它就会工作。如果您有任何此类问题,您可以检查您的版本,以便获得结果。

【讨论】:

    【解决方案2】:
    $config['sess_driver'] = 'files';
    $config['sess_cookie_name'] = 'ci_session';
    $config['sess_expiration'] = 7200;
    $config['sess_save_path'] = NULL;
    $config['sess_match_ip'] = FALSE;
    $config['sess_time_to_update'] = 300;
    

    $config['sess_regenerate_destroy'] = FALSE;

    .htaccess

    DirectoryIndex index.php
    RewriteEngine on
    RewriteCond $1 !^(index\.php|images|css|js|robots\.txt|favicon\.ico)
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ ./index.php?/$1 [
    

    L,QSA]

    【讨论】:

    • 请解释你的答案。
    【解决方案3】:

    我认为使用不正确的语法访问会话数据存在问题。您可以使用以下语法来设置会话数据并获取会话数据。

    设置会话数据的示例

    $session_data = array('name' => "kiran");
    $this->session->set_userdata('user', $session_data);
    

    获取存储会话数据的示例

    $this->session->userdata('user')['name'];
    

    【讨论】:

    • 这个$this->session->userdata('user')['name'];不正确!函数 userdata 声明为:public function userdata($key = NULL),请参见会话库 (/system/libraries/Session/Session.php),您会在第 747 行附近找到它:
    【解决方案4】:

    您的问题有几个部分,我将依次回答。

    关于从会话中检索值

    userdata() 是一种方法。您访问它的方式将其视为一个数组:

    $this->session->userdata['user']['name']; // Bad
    

    As the docs describe,您应该将要检索的值的键作为参数传递给userdata 方法:

    $user = $this->session->userdata('user');
    // Now you can echo $user['name'];
    

    更简单的是使用更新的语法:

    $user = $this->session->user;
    // Now you can echo $user['name'];
    

    关于数据库中的4条会话记录

    检查timestamp 字段。它们显示 3 个不同的时间,这意味着这些是网站上的 3 个独立事件。第一个发生在1501911275,然后 6 秒后有另外 2 条记录,然后 139 秒后有最后一条记录。这些代表对网站的 3 个独立请求 - 可能您正在访问不同的页面,或者测试和重新加载。

    至于为什么会有多条记录,那是因为会话ID会定期重新生成。具体发生的频率取决于您的配置,请参阅sess_time_to_update 配置选项。它们被销毁的频率还取决于您的配置(请参阅文档同一部分中的sess_regenerate_destroy) - 但通常较旧的会话记录会保留一段时间,然后通过垃圾收集清理。因此,虽然您只有 1 个“当前”会话记录,但旧记录可以保留一段时间。

    关于您的sess_save_path

    从您问题的措辞来看,我认为您想使用files 会话驱动程序,并且只尝试了database 驱动程序进行测试。如果这是正确的,那么您的文件会话配置中存在问题,您应该修复它。

    According to the docs:

    $config['sess_save_path'] 仅支持绝对路径。

    config/config.php中的cmets也说:

    警告:仅支持绝对路径!

    您的配置指定会话数据应保存在ci_sessions,这不是绝对路径:

    $config['sess_save_path'] = 'ci_sessions'; // Bad
    

    我不确定将如何解释,但我猜测该目录将不存在,并且 Web 服务器将无权创建它。我无法想象为什么它可以在您的实时服务器上运行。

    将路径更改为绝对路径,并确保您的网络服务器可以写入。 Again from the docs

    mkdir /<path to your application directory>/sessions/
    chmod 0700 /<path to your application directory>/sessions/
    chown www-data /<path to your application directory>/sessions/
    

    (将 www-data 更改为您的 Web 服务器运行的用户)。然后:

    $config['sess_save_path'] = '/<path to your application directory>/sessions/';
    

    【讨论】:

    • @shanil 这有帮助吗?
    • 不,我尝试了所有建议的所有方法,但没有任何效果。最后,我发现了问题,CI 3.1.6 不支持 PHP 7.1,当我回到 5.6 时,它开始保存会话。非常感谢您的帮助。
    • @ShanilSoni 我刚刚使用 PHP 7.0 和全新安装的 Codeigniter 3.1.6 设置了一个 Docker 容器,并且会话工作正常。我觉得不是 PHP 版本问题。
    • @ShanilSoni 如果您尝试了此处建议的所有内容,您会发现这里的其他 2 个答案都不起作用,对吧?
    • 这就是为什么我在自己的回答中提到这可能不是正确的解释,但它以某种方式起作用。是的,这里提到的答案都没有奏效。过去 15 天我一直在尝试解决此错误,对于需要阅读会话的页面,我注释掉了该代码以使其正常工作。
    【解决方案5】:

    如果您阅读Codeigniter Class Reference setuserdata 期望第二个参数是一个值,那么如果第一个参数是一个键,那么就会出现错误。

    使用 Codeigniter 方式,您将无法达到您想要的效果:

    set 像这样:

    $result=array('name'=&gt;'john doe');

    $this-&gt;session-&gt;set_userdata($result);$this-&gt;session-&gt;set_userdata('name','john doe');

    get 像这样:

    echo $this-&gt;session-&gt;userdata(['name']);

    另一方面,使用 vanilla php $_SESSION 你可以像这样实现它:

    设置:$_SESSION['user']=$result;

    获取:echo $_SESSION['user']['name'];

    php manual查看有关 $_SESSION 的信息

    注意:

    令我惊讶的是,同样的代码在服务器上运行时没有任何错误。

    这是由于您的ENVIRONMENT 设置,因为您在生产(实时)服务器上的error_reporting 受到限制。这是在您的根目录index.php 中设置的。

    define('ENVIRONMENT', isset($_SERVER['CI_ENV']) ? $_SERVER['CI_ENV'] : 'development'); 更改为:define('ENVIRONMENT', 'production');,您也不会在本地主机上看到错误。

    更新:

    实际上$this-&gt;session-&gt;set_userdata('name', $name); 有效,但是函数 userdata() 只接受一个参数并期望它是一个字符串

    如果您查看会话库 (/system/libraries/Session/Session.php),您会在第 747 行附近找到它:

    /**
     * Userdata (fetch)
     *
     * Legacy CI_Session compatibility method
     *
     * @param   string  $key    Session data key
     * @return  mixed   Session data value or NULL if not found
     */
    public function userdata($key = NULL)
    {
        if (isset($key))
        {
            return isset($_SESSION[$key]) ? $_SESSION[$key] : NULL;
        }
        elseif (empty($_SESSION))
        {
            return array();
        }
    
        $userdata = array();
        $_exclude = array_merge(
            array('__ci_vars'),
            $this->get_flash_keys(),
            $this->get_temp_keys()
        );
    
        foreach (array_keys($_SESSION) as $key)
        {
            if ( ! in_array($key, $_exclude, TRUE))
            {
                $userdata[$key] = $_SESSION[$key];
            }
        }
    
        return $userdata;
    }
    

    【讨论】:

    • 不,我已经尝试过了。 set_userdata 可以将第一个参数作为名称。我成功地使用了它。
    • @ShanilSoni 请查看我更新的答案,如果您使用 php $_SESSION 可以解决您的问题。实时服务器上没有错误绝对是您的环境设置,我刚刚检查过。
    • 不,我尝试了所有建议的所有方法,但没有任何效果。最后,我发现了问题,CI 3.1.6 不支持 PHP 7.1,当我回到 5.6 时,它开始保存会话。非常感谢您的帮助。
    • 我不知道为什么它在我的本地环境中不起作用。我已经面临这个问题 15 天了。当我切换回来时,它开始工作了。
    • 您是否仔细检查了在本地主机上设置define('ENVIRONMENT', 'production');(如上文所述)。这将抑制错误消息。也许这就是让你感到困惑的地方。
    【解决方案6】:

    似乎问题出在 PHP 7.1 版上,因为 CI 3.1.6 不支持该 PHP 版本。

    我不确定这是否是正确的解释,但是当我切换回 PHP 5.6 版时,一切都开始正常工作了。

    【讨论】:

    • 我刚刚使用 PHP 7.0 和全新安装的 Codeigniter 3.1.6 设置了一个 Docker 容器,并且会话工作正常。我觉得不是 PHP 版本问题。
    • 我也遇到了同样的问题。我刚刚测试并在 PHP 7.0 中运行良好。但是 PHP 7.1 的会话数据存在错误
    • 所有 3.1.x 版本都支持 PHP 7.1。无论问题是什么,100% 都不是那样。
    【解决方案7】:

    关注这些

    在 config.php 中

    Set $config['sess_save_path'] = NULL;
    

    正如你所说的$this-&gt;session-&gt;set_userdata('user',$result); //$result works fine, it produces上面$result应该是这样的

    $result = array(
        'user'  => 'Ab',
        .....
        'logged_in' => TRUE
    );
    

    如何访问会话密钥

    echo $this->session->userdata('user');
    

    $user = $this->session->userdata('user');
    echo $user;
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-05
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2020-12-07
    • 1970-01-01
    • 1970-01-01
    • 2020-03-31
    相关资源
    最近更新 更多