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

Posted

技术标签:

【中文标题】PHP 缓存而不弄乱文件权限(另外,如何在 PHP 中模拟 ASP 应用程序变量)【英文标题】:PHP Caching without messing with file permissions (Also, How to emulate ASP Application variables in PHP) 【发布时间】:2010-10-02 23:50:43 【问题描述】:

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

有人对如何实现这一点有任何建议吗?

以下是我考虑过的一些可能性,任何关于这些的 cmets 都会很有用:

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

再一次,任何关于这些想法或任何新想法的 cmet 将不胜感激。

更新: 我尝试使用 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 上传到一个开箱即用的共享主机帐户。

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

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

【问题讨论】:

【参考方案1】:

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

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

    由于我们正在切换会话 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();
?>

【讨论】:

【参考方案2】:

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

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

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

【讨论】:

【参考方案3】:

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

【讨论】:

并确保缓存子目录是PHP在第一次运行时创建的,所以它是目录的所有者,以后可以写入 …并保护它免受来自互联网的请求。【参考方案4】:

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

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

【讨论】:

【参考方案5】:

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

http://www.php.net/memcache

【讨论】:

memcache 很酷,但这里不是一个选项,因为我无法控制部署脚本副本的服务器。【参考方案6】:

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

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

【讨论】:

以上是关于PHP 缓存而不弄乱文件权限(另外,如何在 PHP 中模拟 ASP 应用程序变量)的主要内容,如果未能解决你的问题,请参考以下文章

更改字体大小而不弄乱 Tkinter 按钮大小

如何在不弄乱内容的情况下标记 dequeueReusableCell?

如何在不弄乱下拉值的情况下使 Angular Reactive Formarray 中的级联下拉菜单工作

如果不弄乱表格格式,就无法分页工作

Php 弄乱了我的上传大小

怎样隐藏一部分php文件路径