PHP缓存而不会弄乱文件权限(另外,如何在PHP中模拟ASP应用程序变量)

时间:2009-01-22 19:04:52

标签: php caching file-permissions application-variables

我正在尝试在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直接创建一个开箱即用的共享主机帐户。

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

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

6 个答案:

答案 0 :(得分:2)

好的,我想通过使用共享/全局会话状态模拟ASP样式的应用程序变量来解决这个问题。我在相关更新中的非工作代码进行了两项重要更改:

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

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

  3. 完整的工作代码如下(清理过来!)。这可以通过在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();
    ?>
    

答案 1 :(得分:1)

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

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

  

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

查看memcached for php-它的效果非常好。

http://www.php.net/memcache

答案 5 :(得分:0)

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

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