Zen Space
php erlang javascript ruby python web linux mac os x
rss
email
twitter
facebook
  • Labs
  • Resume
  • Works
  • About

基于var_export 和 include返回值的缓存方案

no comments
Posted on 七 2 2009 by admin

前一篇文章我们研究了include调用返回值的问题,并指出可以通过这种方式来完成序列化相同的功能,现在我就来研究一下这种方法的可行性和效率,因为直接的返回php值肯定是比unserialize()函数要快。

第一步我们来研究下怎么将php对象持久化的保存起来。下面是我定义的一些变量:
1
2
3
4
5
6
private $_var;
public $pub = array('pub value', 3, 4);
public function __constructor($var)
{
$this->_var = $var;
}
1
2
3
4
5
6
7
8
9
10
public function show()
{
echo $this->_var;
}
}

$string = "It's a string...";
$array = array(1, 2, 'key' => 'value', array('sub-array'));
$number = 135345.55;
$class = new MyClass('class var');
1
2
3
4
5
6
//通过serialize()方法我们可以将他们持久化比如:
echo serialize($string); //s:16:"It's a string...";
echo serialize($array); //a:4:{i:0;i:1;i:1;i:2;s:3:"key";s:5:"value";i:2;a:1:{i:0;s:9:"sub-array";}}
echo serialize($number); //d:135345.5499999999883584678173065185546875;
echo serialize($class); //O:7:"MyClass":2:{s:13:"MyClass_var";N;s:3:"pub";a:3:{i:0;s:9:"pub value";i:1;i:3;i:2;i:4;}}
// 我们可以将这些序列化的结果存到文件中,在需要的时候unserialize()返回得到相应的值,但是现在我不会这么做。

前篇文章提到了通过include返回值来直接取得php值对象,首先我们要把值保存起来,因为我们要通过include来包含它,首先遇到的问题就是我们的序列化函数必须要生成合法的php表达式才行,否则include是无法得到相应的返回值的
比如我们要序列化 字符串 “abcd” 我们可以这么做

1
2
3
4
file_puts_content("data.php", "return 'abcd';");
//然后这样取得相应的值
$string = include "data.php";
echo $string; // 它应该输出 abcd

那数组怎么办呢?比如上面的数组。我们可以自己编写这个序列化函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function encode($var){
if (is_array($var)) {
$code = 'array(';
foreach ($var as $key => $value) {
$code .= "'$key'=>".encode($value).',';
}
$code = chop($code, ','); //remove unnecessary coma
$code .= ')';
return $code;
} else {
if (is_string($var)) {
return "'".$var."'";
} elseif (is_bool($var)) {
return ($var ? 'TRUE' : 'FALSE');
} elseif (is_numeric($var)) {
return "$var";
}
else
{
return 'NULL';
}
}
}

这个函数可以将字符串,数组以及数字变成合法的php表达式。
比如:
file_put_contents(“data.php”, “<?phpn return ” . encode($array) . “;n”);
data.php文件的结果是:

1
return array ( 0 =&gt; 1, 1 =&gt; 2, 'key' =&gt; 'value', 2 =&gt; array ( 0 =&gt; 'sub-array', ), )array(4) { [0]=&gt; int(1) [1]=&gt; int(2) ["key"]=&gt; string(5) "value" [2]=&gt; array(1) { [0]=&gt; string(9) "sub-array" } }

我们的目的达到了。可以直接的通过include这个文件来得到我们的值。
但是现在有个问题,我们没有序列化对象类型的值,这个该怎么处理呢?
一个类对象有对象的状态和对象的行为,行为在类定义完以后就确定了,所以每个类的实例的行为都是一样的。所以我们可以不考虑,我们只需要考虑类对象的状态就可以了,简单来讲就是类的属性状态需要保存起来。那怎么样得到一个类的属性呢?
经过一番搜寻以后发现一个函数
get_object_vars
(PHP 4, PHP 5)get_object_vars — 返回由对象属性组成的关联数组
这个函数可以获得对象的属性关联数组,也就只可以得到对象的状态,但是对象的属性有各种访问控制,get_object_vars()函数在对象外访问只能得到对象的公开属性,而无法得到私有属性,这样的话我们就无法得到对象的全部状态,不可行,但是在对象内可以得到对象的所有属性,那我们可不可以在对象内定义一个___get_properties()方法来返回这些状态呢。
给类增加这样一个方法

1
2
3
4
public function __get_properties()
{
return get_obj_vars($this);
}

这样我们就可以得到类的所有属性了。第一步算是完成了,我们得到状态该怎么重新恢复出来呢?要在对象外部给对象设置属性我们只有两种情况:一种是这个属性是公开属性,我们可以直接赋值 比如: $obj->prop = $value; 如果是私有属性我们则需要自己增加setter方法比如 setProp($value);方法,来设置。但是这就会遇到一个问题,我们的属性要么是公开属性,要么必须要有setter方法来设置,很多情况下我们不希望给类增加这么多没有实际用处的方法,也为了封装性,不会有这么多的setter方法。虽然我们能得到对象的状态,但是却无法恢复对象状态,这样的话,我们的序列化方法也就没有什么意义了。我们探索到现在算是失败了。
解决办法:var_export()函数。
在看symfony代码的时候发现了这个函数,手册是这么描述的:
———
var_export
(PHP 4 >= 4.2.0, PHP 5)var_export — 输出或返回一个变量的字符串表示
描述
mixed var_export ( mixed expression [, bool return] )

此函数返回关于传递给该函数的变量的结构信息,它和 var_dump() 类似,不同的是其返回的表示是合法的 PHP 代码。

您可以通过将函数的第二个参数设置为 TRUE,从而返回变量的表示。

这个就是我们想要的那个函数,我们来看看这个函数是怎么使用的。

1
2
3
4
5
//变量继续使用上面定义的变量
echo var_export($string); //'It's a string...'
echo var_export($array); /* array (0 =&gt; 1, 1 =&gt; 2, 'key' =&gt; 'value', 2 =&gt; array (0 =&gt; 'sub-array', ),)*/
echo var_export($number); // 135345.55
echo var_export($class); /* MyClass::__set_state(array('_var' =&gt; NULL, 'pub' =&gt; array (0 =&gt; 'pub value', 1 =&gt; 3, 2 =&gt; 4)) */

我们可以看到生成的都是合法的PHP表达式。通过设置第二个参数为true,就可以将返回结果赋值给变量比如$new_array_string = var_export($array, TRUE);然后将这个结果写入文件持久化

file_put_contents(“data.php”, “public function __constructor($var)
{
$this->_var = $var;
}

public function show()
{
echo $this->_var;
}
public static function __set_state(array $array)
{
$tmp = new MyClass();
foreach($array as $key => $value)
{
$this->$key = $value;
}
}
}

// 一些变量
$string = “It’s a string…”;
$array = array(1, 2, ‘key’ => ‘value’, array(’sub-array’));
$number = 135345.55;
$class = new MyClass(‘class var’)

// 缓存
cache(“string.data.php”, $string); // 当然扩展名不一定非得php, 文件名我也只是简单的处理
cache(“array.data.php”, $array);
// 等等。。。

// 获取数据,当然也可以在其他文件中来获取。
$class = cache_get(“class.data.php”);

参考:http://www.thoughtlabs.com/2008/02/02/phps-mystical-__set_state-method/?dsq=12016456


Category: PHP

Leave a Reply

点击这里取消回复




最近文章

  • 开启Mac OS X Snow Leopard的NTFS原生读写
  • 在2009的尾巴上
  • 支持IPv6的Tunnelblick For Mac OS X OpenVPN客户端
  • Lockerz邀请
  • 在PHP中检查PHP文件是否有语法错误

分类目录

  • G-related (1)
  • Hackintosh (1)
  • JavaScript (1)
  • Mac (4)
  • PHP (5)
  • 乱78糟 (1)
  • 未分类 (4)

标签~云

2009 debug editor exception html JavaScript Mac MacFUSE MacOSX NTFS OS X PHP Snow Leopard softwares ssh syntax check Tools VPN

一些脚印

  • reeze 在 Mac OS 启动sshd服务 上的评论
  • birdbluebloc 在 Mac OS 启动sshd服务 上的评论
  • kevin 在 Lockerz邀请 上的评论
  • reeze 在 Lockerz邀请 上的评论
  • kevin 在 Lockerz邀请 上的评论

Google Reader

  • Xen 初学者指南 | LinuxSir.Org (www.linuxsir.org)
  • 45个吸引人的创新简历 (玩聚SR|最佳)
  • 美女与手机 (陈方毅的灵感日志)
  • 网页表单中的行为也分主次 (所有文章 - UCD大社区)
  • 9 本免费的 Python 语言编程书籍 (LinuxTOY)
Shared Items

日志存档

  • 2010年一月 (1)
  • 2009年十二月 (3)
  • 2009年十月 (2)
  • 2009年七月 (4)
  • 2009年六月 (4)

链接表

  • Ideawu
  • LinuxToy
  • on Github
  • Tina的设计天地
  • 风雪之隅
想读
Programming Collective Intelligence
Collective Intelligence in Action
旅行的艺术
操作系统设计与实现(第三版)(上册)
操作系统概念(第六版 影印版)
正读
Even Faster Web Sites
构建高性能Web站点
晨間日記的奇蹟
深入理解LINUX内核(影印版第3版)
Linux Kernel Development (2nd Edition)
读过
应用Rails进行敏捷Web开发
追风筝的人
构建可扩展的Web站点
Restful Web Services
PHP 5权威编程

  • Resume
  • Works
  • About
Powered by Wordpress  |  Designed by WebTreats