问题 使用PHP缓存MySQL查询结果的最简单方法?


每次有人登陆我的页面 list.php?id=xxxxx 它重新查询一些MySQL查询以返回:

$ids = array(..,..,..); // not big array - not longer then 50 number records
$thumbs = array(..,..,..); // not big array - not longer then 50 text records
$artdesc = "some text not very long"; // text field

因为我从中进行查询的数据库非常大,所以我想将这个结果缓存24h,可能是这样的文件: xxxxx.php 在/ cache /目录中,所以我可以使用它 include("xxxxx.php") 如果它存在。 (或txt文件!?,或任何其他方式)

因为有非常简单的数据我相信它可以使用一些PHP行来完成,而不需要使用memcached或其他专业对象。

我的PHP非常有限,有人可以只为这个任务放置PHP主线(或代码)吗?

我真的非常感谢!


6688
2018-04-01 15:19


起源

我已经修改了为24小时缓存有效性添加解决方案的答案。看到 stackoverflow.com/a/15748442/369005 - Hamid Sarfraz


答案:


缓存PHP数组非常简单:

file_put_contents($path, '<?php return '.var_export($my_array,true).';?>');

然后你可以把它读出来:

if (file_exists($path)) $my_array = include($path);

你可能也想 看看ADOdb,它在内部提供缓存。


8
2018-04-01 15:24



非常感谢您采用这种方式来解决这个问题。它确实指出我为我的案例建立一个简单的解决方案! - Pedro P


尝试使用序列化;

假设您将数据放在两个数组中 $array1 和 $array2。现在你要做的是将这些数组存储在文件中。将字符串(问题中的第三个变量)存储到文件很容易,但要存储数组,首先必须将其转换为字符串。

$string_of_array1 = serialize( $array1 );
$string_of_array2 = serialize( $array2 );

下一个问题是缓存文件的命名,以便您可以轻松检查相关阵列是否已在缓存中可用。执行此操作的最佳方法是创建mysql查询的MD5哈希并将其用作缓存文件名。

$cache_dir = '/path/cache/';

$query1 = 'SELECT many , fields FROM first_table INNER JOIN another_table ...';
$cache1_filename = md5( $query1 );

if( file_exists( $cache_dir . $cache1_filename ) )
{
    if( filemtime( $cache_dir . $cache1_filename ) > ( time( ) - 60 * 60 * 24 ) )
    {
        $array1 = unserialize( file_get_contents( $cache_dir . $cache1_filename ) );
    }
}

if( !isset( $array1 ) )
{
    $array1 = run_mysql_query( $query1 );
    file_put_contents( serialize( $array1 ) );
}

重复上面的另一个数组应该存储在一个单独的文件中,第二个查询的MD5用作第二个缓存文件的名称。

最后,您必须确定缓存应保持有效的时间。对于相同的查询,可能会更改mysql表中的记录,这些记录可能会使您的文件系统缓存过期。因此,您不能仅依靠唯一的文件名来进行唯一查询。

重要:

  • 必须删除旧的缓存文件。您可能必须编写一个例程来检查目录的所有文件并删除早于n秒的文件。
  • 将缓存目录保留在webroot之外。

5
2018-04-01 17:40



以为我明白了。将尝试按照您描述的步骤实施它。非常感谢哈米德。 - Pedro P


只需编写一个名为$ _GET ['id']的新文件和要缓存的内容,每次检查该文件是否存在,否则创建一个。像这样的东西:

$id = $_GET['id']

if (file_exists('/a/dir/' . $id)) {
  $data = file_get_contents('/a/dir/' . $id);
} else {
  //do mysql query, set data to result
  $handle = fopen('/a/dir/' . $id, 'w+');
  fwrite($handle, $data);
  fclose($handle);
}

0
2018-04-01 15:26



然后有人用你的脚本调用 script.php?id=../../etc/passwd 或其他有趣的东西。消除用户输入... - DCoder
Ty lemondrop;据我所知,文件本身没有任何扩展名,对吧?如何在$ data中放入我的3个项目(2个数组+ 1个变量)?另外,如果你能为我提供检查24小时缓存的方法,那就太棒了! - Pedro P