1

我正在尝试在 PHP 脚本中实现某种缓存,该脚本将发送到许多不同的客户端/站点,这些客户端/站点将由相当非技术的用户使用各种 Web 主机进行部署。由于用户的非技术性质,我想避免要求他们调整文件权限。缓存需要跨会话,因此不使用会话变量。如果我在 ASP 中对此进行编码,我会使用应用程序变量,但它们在 PHP 中不存在(据我所知)

有没有人对如何做到这一点有任何建议?

以下是我考虑过的一些可能性,对此的任何评论都会很有用:

  • 通过系统临时文件夹中的文件进行缓存 - 我可以使用 sys_get_temp_dir() (或 PHP4 上的一些家庭推出的类似函数)来帮助找到这样的文件夹。这里的缺点是它可能不适用于使用 openbase_dir 限制的主机
  • 我看过的一些网站提到欺骗 PHP 使所有用户会话共享相同的会话状态,从而迫使会话变量像会话变量一样工作。当然,我现在找不到那个帖子了……无论如何,这似乎很可怕。(一旦我再次找到它,我会用这个帖子的链接更新这个问题)
  • 使用像亚马逊的简单存储服务这样的第三方数据存储——看起来有点矫枉过正
  • 在我控制的服务器上缓存数据,并让客户端在每次点击时从那里下载新数据。

再一次,对这些想法或任何新想法的任何评论将不胜感激。

更新:我尝试使用 session_id() 来使用共享会话状态,但它不起作用。每个会话都维护自己的“GlobalCache”,有什么想法吗?:

// This code doesn't work, but the similar code in my answer does!

function test() {
    if (!$_SESSION['session_count']) $_SESSION['session_count'] = 0;
    $_SESSION['session_count']++;


    $count = get_cache( 'count' );

    print "pre application count: $count<br>";

    if ( !$count )
        $count = 0;

    $count++;

    print "session_id: " . session_id() . "<br>";
    print "post application count: $count<br>";
    print "session_count: " . $_SESSION['session_count'] . "<br>";

    set_cache('count', $count);
}


function set_cache( $name, $value ) {
    $old_session = session_id();
    print "old_session (set): $old_session<br>";

    session_id("GlobalCache");
    print "new_session (set): " . session_id() .  "<br>";

    $_SESSION[$name] = $value;
    session_id( $old_session );
}

function get_cache( $name ) {
    $old_session = session_id();
    print "old_session (get): $old_session<br>";

    session_id("GlobalCache");
    print "new_session (get): " . session_id() .  "<br>";

    $value = $_SESSION[$name];
    session_id( $old_session );
    return $value;
}

session_start();
test();

更新:有些人建议使用 memcached,这实际上对某些人来说是一个很好的解决方案,但由于我无法控制终端服务器环境,所以它不是一个选项。这个想法是有一个脚本,人们可以通过 FTP 上传到一个开箱即用的共享主机帐户。

更新:有人建议使用脚本创建我自己的缓存文件夹,但我不需要在已经具有写入权限的文件夹中创建这样的文件夹吗?

更新,找到解决方案:我最终找出了我的全局会话脚本中的问题,并为此发布了我自己的答案。感谢大家的帮助。

4

6 回答 6

2

好的,我想出了如何通过使用共享/全局会话状态模拟 ASP 样式的应用程序变量来做到这一点。相关更新中我的非工作代码的两个关键更改:

  1. 要切换会话状态,我们必须结束当前会话,切换到新会话,然后启动它。我已经将此过程封装在 switch_session() 中

  2. 由于我们正在切换会话 ID,因此我们必须使用 ob_start()/ob_end_flush() 缓冲页面的输出,以便不会过早发送会话 cookie。

完整的工作代码如下(也清理了!)。这可以通过在 IE 和 Firefox 窗口中加载页面并重新加载几次以观察计数器上升来轻松测试:

<?php
function test() {

    // Do a regular session count
    print "session_id: " . session_id() . "<br>";
    if (!$_SESSION['session_count']) $_SESSION['session_count'] = 0;
    $_SESSION['session_count']++;
    print "session count: " . $_SESSION['session_count'] . "<br>";


    // Do an application count
    $count = get_cache( 'count' );
    if ( !$count ) $count = 0;
    $count++;
    print "application count: $count<br>";
    set_cache('count', $count);
}


function set_cache( $name, $value ) {
    $old_session = switch_session("GlobalCache");
    $_SESSION[$name] = $value;
    switch_session( $old_session );
}

function get_cache( $name ) {
    $old_session = switch_session("GlobalCache");
    $value = $_SESSION[$name];
    switch_session( $old_session );
    return $value;
}

function switch_session( $session_id ) {

    // switch the session and return the original
    $old_id = session_id();

    session_write_close();
    session_id($session_id);
    session_start();
    return $old_id;
}

ob_start();
session_start();
test();
ob_end_flush();
?>

于 2009-01-23T01:58:19.330 回答
1

您可以使用具有固定会话密钥的会话。

http://de.php.net/manual/en/function.session-id.php

session_id([id]) 用于获取或设置id当前会话的会话。如果指定了 id,它将替换当前会话 id。为此,需要在 session_start() 之前调用 session_id()。

于 2009-01-22T19:18:42.867 回答
1

在应用程序的目录中使用您自己的缓存目录。因此,您不必为各种服务器和/或 PHP 设置而苦恼,并获得最佳的可移植性。

于 2009-01-22T19:23:22.017 回答
0

我投票赞成“在我控制的服务器上缓存数据,并让客户端在每次点击时从那里下载新数据”。

所有其他路径都会导致某种疯狂。

于 2009-01-22T19:10:31.090 回答
0

查看 memcached 的 php - 它工作得非常好。

http://www.php.net/memcache

于 2009-01-22T20:42:11.840 回答
0

我使用作者的更新函数作为缓存简单数据库查询结果的一种方式,因为我期待高负载。我还存储了一个时间戳,以便我可以定义页面更新数据库结果的频率,而不仅仅是获取缓存值。

我可以告诉你,这个缓存函数的性能比在每次请求时直接访问数据库要差得多。我实际上杀死了服务器。一旦我切换回简单地查询数据库,服务器就会全速运行,甚至没有注意到相当大的负载。

于 2010-01-22T13:25:53.473 回答