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

解决Mac下终端中使用screen管理回话但看不到滚动条等问题

no comments
Posted on 七 2 2010 by reeze

工作中开发基本都是ssh到远程服务器上vim开发,有时候因为网络原因或者不小心把终端给关了或者网络出现问题以后就痛苦了,因为vim默认会用swp文件保存修改,我又不想关掉这个功能,一不小心真丢数据就划不来了,非法关闭vim之后再次打开就会提示是否恢复文件,自从发现screen这个绝佳的绘画管理工具,就深深的爱上了它,IBM的这篇文章有详细的介绍 “linux 技巧:使用screen 管理你的远程会话”。在使用过程中发现一些问题,默认快捷键是Ctrl + A, 用惯了命令行的人肯定会用Ctrl +A , Ctrl + E来定位当前输入的命令吧. 在~/.screenrc中修改一下就可以了,下面是我的.screenrc

1
2
3
vbell_msg "" # 比如在tab自动提示的时候,默认总是会出现一个Wuff,觉得很烦,关掉
escape ``  # instead of Control-a  使用 反引号当快捷键,因为用的相对较少
termcapinfo xterm* ti@:te@  # 这个就是解决mac下看不到滚动条的问题了

解决方法来源见:http://stackoverflow.com/questions/1039442/mac-os-x-terminal-apps-buffer-and-screen-command


  Tags: linux, Mac, screen, screenrc Category: Mac, tips

让你的网站也像Gmail一样支持文件拖放上传-HTML5之File API

10 comments
Posted on 四 25 2010 by reeze

如果你比较好奇,可以先从这里下载所有代码,也可以点击这里查看chrome下上传的demo,点这里查看firefox下的demo

前不久Gmail推出了支持拖拽的附件上传功能,试用了下还真不错,其实很久以前就在想能有直接拖拽附件的功能,多亏有了HTML5,Web应用越来越像客户端的应用了。

在好奇心驱使下,想了解一下Gmail到底是怎么做到的,了解了一下最新的HTML5 File API草案,这个接口主要提供的就是提供对文件对象的访问,别想歪了,这个接口是无法随意的访问系统里的文件的。他能做的就是访问<input type=”file” />标签里所选择的文件,这些文件可以通过用户手动选择,或者是HTML5的拖放接口选中的文件。有兴趣的童鞋可以看看这个规范,还算比较简单。

下面简单看看接口定义几个对象。

FileList、File对象。

在HTML5中的<input type=”file” />标签中增加了mutilple属性,允许进行多文件选择。大家应该都知道一般上传标签中是不允许选择多个文件的。 新增的这个属性就是允许进行多个文件的选择(这个在桌面应用中也很常见)。<input type=”file” multiple=”multiple” id=”file” />

下面是在Firebug中的输出

1
2
3
4
5
>>> var f = document.getElementById("file")
>>> f.files
FileList0=File length=1 // 选中的文件数量
>>> f.files[0]
FilefileName=es.dll fileSize=271360

FileList对象就是用户选择的所有文件的对象表示,如果是通过input标签选择的,就可以通过上面代码所示的方法进行访问,File对象就可以刚才选择的某个文件的信息,如上面的代码所示,主要可以得到所选中的文件名以及文件大小信息。

你可能在想只能得到这些信息到底有什么用呢?都没有办法读取文件内容,这就得提到规范中的FileReader接口了,这个接口就是用来读取File对象文件的。

在File API规范中提到File API主要是和其他的接口协同合作。比如XMLHttpRequest (这个新接口支持通过xhr的send()方法发送File对象), DataTransfer(也就是HTML5中的拖拽接口 ), 以及Web Worksers(这个主要是异步脚本执行,相当于给JS提供了“多线程”脚本执行能力,并且支持通过postMessage()进行“线程间通信”),感兴趣的,可以看看这篇日志,以及这篇。

目前能实现这样的效果的方式主要有如下几种:

  • Gmail中提到的这两个浏览器都支持拖放接口,托放以后可以直接通过托放事件的DataTransfer属性访问到本次托放是关联的文件对象列表FileList,然后通过XMLHttpRequest的send方法将File对象发送到服务器
  • 在Chrome下支持直接将文件拖放到文件选择控件上,就相当于直接选择了文件。这时可以通过<input type=”file” />DOM对象的files属性访问到被托放进来的文件列表对象,然后也可以通过Ajax将文件对象发送到服务器,通过将文件选择控件透明度降低也可以实现Gmail类似的效果。 在Chrome因为可以直接通过托拽的方式让文件选择控件“赋值”,此时也可以通过一个iframe加表单的方式将数据发送到服务器。
  • 在Firefox3.6下可以通过FileReader直接读取到文件的内容,然后直接将文件内容发送到服务器端(可以参考这个例子,这是个不完整的例子,直接浏览是看不到效果的,查看源代码你就会懂的。)

下面就来看看Gmail到底是怎么做到的吧。

本来想通过Firebug的概况功能来捕捉到在托拽期间的脚本执行情况,比如:


但是脚本执行里压根没有找到ajax相关的函数调用,可能是因为firebug还不支持监控页面里嵌入的iframe中的脚本执行跟踪,这也说明本次上传肯定是在某个iframe中完成的。,那就直接监听网络吧,托拽上传一个附件时查看网络情况,发现附件是通过下面的ajax post过去的:

大家注意看,是通过ajax post方式将附件POST到服务器的,


可以看出Gmail在firefox下不是通过表单直接提交实现的。在chrome下的开发人员工具有点简单,无法看到网络情况,我也懒的再去抓包看了,估计是使用透明<input type=”file” />+ajax方式实现的。

在Gmail支持托拽的声明中提到目前只支持Chrome 2+以及FireFox3.6+。虽然这两个浏览器都支持HTML5,但是对于所有规范的支持程度都是不一样的,并且规范也还不是正式规范。在Firefox3.6的release note中提到:

Support for new DOM and HTML5 specifications including the Drag & Drop API and the File API, which allow for more interactive web pages.

开始支持了HTML5的拖拽接口以及File API。


下面根据浏览器以及HTML5的规范整理出两个浏览器下实现类似Gmail 上传附件的代码。

点击这里下载所有代码,有兴趣的童鞋查看源代码就知道怎么回事了,有一定的注释:)

也可以点击这里查看chrome下上传的demo,点这里查看firefox下的demo,之所以分开是为了简单起见,当然你真的想要给你的网站提供托拽上传功能,你就得自己去同时兼容这两个浏览器啦,相信这也不是件困难的事情:)


  Tags: File API, Gmail, HTML5, 托放上传 Category: HTML5, 未分类

开启Mac OS X Snow Leopard的NTFS原生读写

no comments
Posted on 一 24 2010 by reeze

在Mac OS X下一直使用MacFUSE和NTFS-3G来访问ntfs分区,这次装了Snow leopard 10.6.2之后出现fusefs.kext can’t load的错误,从官方得知目前macfuse在snow leopard下有问题,在网上看到这篇贴子提到Snow Leopard其实原生就支持NTFS分区的读写,真是个好消息。

开启的方法有两种:
一种是在/etc/fstab文件里增加挂载选项,基本步骤是:
1,卸载NTFS-3G或者其他读写ntfs分区的软件
2,打开终端$ diskutil info /Volumes/分区名 或者使用磁盘工具获得分区的UUID
3,编辑/etc/fstab文件,增加一行 UUID=分区的UUID none ntfs rw
4,如果还有其他的分区要挂载,则继续上面的步骤2-3增加其他分区

这种方式比较烦琐,第二种方法就比较简单。
大家应该都注意过系统已启动就会自动挂载所有的ntfs分区,这个命令在/sbin/mount_ntfs
这个方法所要做的就是给这个默认的挂载命令增加可读写参数,按如下步骤在终端命令行操作:
$ sudo mv /sbin/mount_ntfs /sbin/mount_ntfs.orig
$ sudo vim /sbin/mount_ntfs
编辑这个文件,加入如下内容:
#!/bin/sh
/sbin/mount_ntfs.orig -o rw “$@“ #这里调用默认的挂载命令,不过增加了 rw参数,开启读写

保存这个文件,然后:
$ sudo chown root:wheel /sbin/mount_ntfs
$ sudo chmod 755 /sbin/mount_ntfs

然后重启,启动后,你应该就能得到一个可以自由读写的ntfs分区了。不过声明一点,这个功能据说不稳定,不知道是因为版权原因还是真的很不稳定,苹果默认没有开启这个功能。不过我更相信苹果。

========
后话:刚好公司配了一台Dell E6400,偶尔看到有人在上面装了一个Leopard,于是手痒也在上面装了一个,如果有人也有这台笔记本也可以试试看,不过我装好的系统还是有问题:

1,触摸屏一碰就乱跑,我直接禁用就好了,反正也不喜欢用。
2,关机和重启不断电,每天关机的次数也有限,也就无所谓了。
3,声音控制不了,只能在具体的应用程序里控制。
其实问题还是挺多的,不过基本上的使用我觉得还是没什么问题的,触摸屏的问题比较烦人,还好我不喜欢用触摸屏。如果有人也想尝试可以试试看。我用的安装文件是 Snow_Leopard_10.6.1-10.6.2_SSE2_SSE3_Intel_AMD_by_Hazard.iso, 至于安装方法PCbeta上有很多的教程可以参考,摸索一下大概都没有什么问题,安装的时候一定要做好备份,因为我到目前已经因为装Mac OS X丢失了不下10次数据了,大部分情况下都是分区被合并。所以一定要小心一点。


  Tags: MacFUSE, NTFS, OS X, Snow Leopard Category: Hackintosh, Mac, 未分类

在2009的尾巴上

1 comment
Posted on 十二 31 2009 by reeze

09年最后一篇日志,充个数吧:)

哈哈,刚买了本《Orange S: 一个操作系统的实现》,这一年下来买了挺多的书,也从图书馆借了很多的书(马上就要毕业了,再也享受不到学校图书馆丰富及时的藏书了,计划以后每个月发工资都买一本自己喜欢的书),发现我读书最大的问题是多而不精,拿一本好书就使劲的翻,很多书都是花几天就翻完了,但是读下来之后总觉得收获不够,一些很需要实践的部分也没有及时联系,总感觉自己浮在表面上,只知其然。所以呢,这个2010年争取多读好书,踏踏实实的啃几本好书,然后就是要多动手啦。

计划2010年呢,能把耽搁很久的想法付诸行动,做出点东西来。希望有个好的开始吧!

Happy New Year!!!


  Tags: 2009

支持IPv6的Tunnelblick For Mac OS X OpenVPN客户端

1 comment
Posted on 十二 30 2009 by reeze

在yegle那里买了OpenVPN服务 ,用着还挺不错,我也在教育网,所以只能使用支持IPv6版的客户端,openvpn默认不支持IPv6,不过yegle提供了相应的IPv6补丁,在Linux下以及Windows下使用的都挺好,最近又在折腾电脑,装了个Snow Leopard,基本没什么问题了,除了我的ATI 2600 XT硬件加速暂时无解外其他的都挺爽,使用了yegle推荐的Tunnelblick, 总是连接不上,它提示让我查看日志,但是根本就找不到地方看日志,直接cd 到 Tunnelblick的包里面直接执行openvpn命令,提示不支持udp6 ,又是不支持 Ipv6,本想直接自己编译一个openvpn,但是想想那样就太不clean了,编译成app的话可以通用,还能共享给有需要的人多好啊,去google code checkout了一份代码,直接编译,错误百出,我是在Snow Leopard上编译的,仔细查看原来需要MacOSX10.4u的SDK 重新安装10.4的SDK还是未果,后来发现SDK的安装目录居然不一样。。自己手动拷贝过去也不行。。 切换到傲Leopard下安装,折腾了好久终于编译成功,废话太多了。呵呵,共享出来给需要的人吧:)

猛击这个连接 下载http://code.google.com/p/tunnelblick-ipv6/downloads/list
可惜的是yegle不再提供IPv6用户的续费了,不过我到期之后差不多也要从学校滚蛋了。
我提供的这个版本的tunnelblick的配置文件位置是 ~/Library/openvpn 最新版的配置放在 ~/Library/Application Support/Tunnelblick/Configuration目录里面。

马上2009年就要过去了。最近很久都没有更新日志了,其实之间也想写一些东西,但是都丢在草稿箱里没写完。论文还有很多没有写完,马上就要交了,要抵制住诱惑乖乖写论文。


  Tags: MacOSX, Tools, VPN Category: Mac, 未分类

Lockerz邀请

6 comments
Posted on 十二 5 2009 by reeze

刚上论坛发现Locker这个好玩的东西

Lockerz (http://www.lockerz.com/)是一个新型态的网站,它成立于09年3月,由美国最大的媒体公司之一美国有线电视公司Liberty Media投资建立,目标是整合影音、游戏、购物等多项服务。 网站为免费注册,但是现阶段只有被邀请的人才可以注册。

Lockerz怎么玩儿?

lockerz的积分点数叫做PTZ,好吧,你可以把它理解为何Q币是一类的东西
使用者只要每天登入(2PTZ) 、回答当日的问题(2PTZ以上,有时会加倍放送)
或邀请朋友加入(2PTZ) ,就可以赚取积分点数

这些点数是可以拿来换一些不错的东西,
例如Apple MacBook、Ipod nano、Ipodshuffle,甚至还有motocycle
依奖品本身价值,换取点数也不同。
目前2PTZ大约可以换取相当于1美金的东西,
例如旧版ipod shuffle(价值$50)100PTZ、ipodnano(价值$150)300PTZ等,
所以奖品并不难换。
刚加入的使用者,
会让你玩一个接方块的游戏,等于白送你美元的
在限定时间内,方块会一直掉下来,价值1PTZ至3PTZ,方块越小越值钱!

另外右下角还有一个DAILIES按钮,
点进去可以回答当日的问题。
每天都是一题随便可以回答的问题,
回答完就可以拿2~10PTZ。

更多的服务和功能还在完善之中……

如何加入Lockerz?

目前Lockerz只有通过邀请才能加入。需要的同学可以在下面留言,留下你的Email,目前已知QQ邮箱接收到邀请最快。
或者可以直接用留言时填写的Email。长时间没有收到的请告诉我一声,我会重新发送。

另外,邀请函有可能在你的垃圾邮件里。

接收到邀请的同学注册后可以再邀请他人,每邀请1位朋友可以获得2个PTZ,这也是获得PTZ的一种方式。

来看段视频吧:


在PHP中检查PHP文件是否有语法错误

1 comment
Posted on 十 9 2009 by reeze

之前在当当的时候的一个项目中用到了一个简单的模板引擎,其实也是借鉴discuz来做的模板引擎,很简单,它所作的事情就是把一些自定义的标签编译成php代码。已经说了很简单了,所以编译的时候也名优进行模板语法的检查,那么在开发过程中就会出现编译出来的php文件有语法问题,有语法问题没有关系,我修改重新编译一下就好了。首先不能在每次请求的时候都把php模板重新编译一下,会严重影响性能,折中的处理时在每个编译好的php文件末尾检查一下该模板文件是否已经修改过,根据设定的更新频率,如果又需要则重新编译模板文件,现在的问题是编译出来的php文件自己有语法错误,根本执行不到模板检查那一步,所以即使修改了模板文件中的问题也不会重新编译。 所以我想寻找一种简单的方法来检查生成的php文件是否合法。不合法就重新编译,这样开发过程中就不用出现错误就得手动删除缓存文件了。

在网上找了一下。刚开始以为 token_get_all()函数能处理语法错误的问题,结果发现,它只是做简单的词法分析。没有办法。后来到论坛上去问了一下

http://groups.google.com/group/professional-php/browse_thread/thread/b8581f6b07b10ff0/2601a63c406bb1c1?lnk=gst&q=reeze#2601a63c406bb1c1

有人告诉我有这样一个函数 php_check_syntax() http://www.php.net/manual/en/function.php-check-syntax.php 我想问题就这么坚决了。。我真应该RTF(Read The Fuck Mannual). 仔细一看。这个函数已近被弃用了:
Note: For technical reasons, this function is deprecated and removed from PHP. Instead, use php -l somefile.php from the commandline.

这个technical reason 到底是什么呢? 先不管了,以后再慢慢研究,反正不能使用这个方法就对了。
他们的建议是使用命令行$php -l filename.php 来检查语法。
Gary Every给了我一个代码片段参考:

在命令行下检查问题也不大。如果我要放在在线应用呢? 这就涉及到可移植性的问题了。首先是操作系统,然后就是环境变量。这样的话就会依赖于服务器端的配置。在http://www.php.net/manual/en/function.php-check-syntax.php 上有人贴出了自己的php_check_syntax()函数实现。
有的采用的就是上面的命令行的方法。
后面有提到使用eval的方法来验证。eval方法会执行传入的代码, 如果代码有语法错误则会抛出parser error, 可以使用’@'错误抑制符去掉错误信息,eval和echo一样并不是函数,不能使用变量函数的方法调用比如:
$func = ‘eval’
$func()这样的调用就是无效的。它会提示没有eval函数,如果你自己定义这么一个函数也是有问题的。因为eval是一个关键字。
eval调用和include差不多,如果被包含文件中没有明确return就返回null。如果直接eval我们需要检查的文件会造成被检查的文件内代码被执行,这可不是我们想要的,我们只需要检查一下这个文件的语法是否正确。 我们可以在要检查的文件之前添加return 语句,让代码提前跳出,那么后面的代码就不会执行了。好的,就这么干。代码如下:
checker.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

if(!function_exists('php_check_syntax')) {
    function php_check_syntax($file_name, &$error_message = null) {
        $file_content = file_get_contents($file_name);
       
        $check_code = "return true; ?>";        
        $file_content = $check_code . $file_content . "<?php ";
               
        if(!@eval($file_content)) {
            $error_message = "file: " . realpath($file_name) . " have syntax error";
            return false;
        }
       
        return true;
    }
}

if(!php_check_syntax("file.php", $msg)) {
    echo $msg;
}
else {
    echo "Woohoo, OK!";
}

file.php

1
2
3
<?php
foreach:: a => b
?>

因为Parse error 是没法被 set_error_handler处理函数处理的。这个异常没办法catch到。所以才使用了@来抑制错误。这带来的问题就是我们无法得到详细的错误信息。 不过目前我需要的功能也只是检查语法是否正确。不正确的话重新编译模板文件,就这么简单,至于语法错误,在显示网页的时候自然会看得到。
最好的办法就是这个被遗弃的php_check_syntax这个方法回到php中。下次再研究下他们是出于什么原因把这个函数去掉的。
////////思维很混乱,写的每一点条理性,谁让我语文那么烂涅。


  Tags: PHP, syntax check Category: PHP

实现一个简单在线HTML编辑器

3 comments
Posted on 十 9 2009 by reeze

一直没有仔细研究过在线HTML编辑器,以前以为编辑功能很复杂,需要用大量的JavaScript来模拟编辑器的效果,以前都是使用一些开源的HTML编辑器,HTML在各网上随处可见,发表文章,评论。最近自己想做一个类似Things这样的Web版的应用,需要一个想Google  Notebook(可惜的是现在已经停止开发了) 那样的编辑功能,看看现在网上的这些编辑器都庞大了,都是一些自己根本用不到的功能,其实我的需求很简单:简单的编辑既可以,并且需要轻量级一些,因为页面上可能需要开很多个编辑器实例。 所有想自己也来研究一下,看看能不能自己开发一个。

几天前花了一个晚上用firebug看了下Google Docs是怎么做。第一个遇到的问题就是如何让光标停在鼠标点击所在得地方。我刚开始一味都是js模拟出来的,这得有多复杂啊。并且还要兼容各个浏览器,天啊!后来上网一搜发现,浏览器早就想到了我们会有这样的一个需求。其实很简单,两条语句就可以说明HTML编辑器的最为核心的部分:

1
2
document.designMode = 'On';
document.contentEditable = true;

参考Mozilla上的这篇文章,介绍了HTML编辑的基本信息,要自己DIY一个常用功能的HTML编辑,这篇文章已经够你用的了。

在你的网页中嵌入这两条语句试试看:),你就会发现你的网站整个得都变的可以编辑了。可以随便乱修改。 不过放心,这样修改并不会破坏你的网站, 当然你也不希望你的整个网站是可以编辑的。例如我们只希望别人发布一条评论,只希望评论输入框可以输入。 要实现这样的效果可以有两种做法:

第一种就是使用直接让某个元素变成可编辑的例如:

index.html

1
2
3
4
5
Test TextEditor
<h1>Hi, HTML Editor!</h1>
<textarea id="content">Hello, you comment please</textarea>
<div id="comment" onclick="editAble('comment')">Your comment</div>
<button onclick="gethtml('comment')">Get HTML</button>

点击该区域后该区域的内容就变成可以编辑的了,这是我们就是对其进行简单的编辑。你可能会觉得直接编辑的功能太简单了,比如想要插入链接或者图片什么的。就没有办法了。这些功能浏览器并没有帮我们做好,不过实现这些功能也不麻烦, 参考上面Mozilla的文档。浏览器都提供了常用的功能API。

一般的编辑器都会提供一个工具栏之类的按钮来编辑文本内容。比如我使用的WordPress提供的编辑器:

wordpress提供的编辑器

wordpress提供的编辑器

可以对文字内容进行操作,加粗下划线,字体,对齐等等,并且提供可视化以及HTML编辑模式。

这个和FCKeditor 以及tinymce之类的编辑器使用的编辑方式和上面我提到的直接编辑html对象的方法不一样,他们使用的是iframe,使用iframe有很多好处,iframe中的文档和当前文档并不会因为样式或者HTML结构而影响到彼此,所以大部分的编辑器都是使用这种方式。它们基本的方式都是:

  1. 在页面中使用一个不可见的字段比如:“input, textarea”之类表单字段,他们的值就是需要编辑的内容。
  2. 页面初始化好,比如载入编辑器相关的一些脚本,也是就是window.onload好以后。创建一个iframe来显示可编辑区域,iframe初始化好以后读取父窗(相对于这个iframe)口的这个不可见表单值的内容,使之成为iframe中的body的html,也就是把所有需要编辑的内容添加到iframe中
  3. iframe中的内容初始化好以后,在iframe中执行上面提到的:
    1
    2
    document.designMode = 'On';
    document.contentEditable = true;

    把iframe整个窗口变成可以编辑的

  4. 进行编辑,这时候的编辑可能需要一个工具栏,基于同样的原因,一般工具栏也会是一个iframe,显示它们自己的编辑按钮。编辑是就利用浏览器提供的接口来对ifame中的内容进行编辑
  5. 父窗口中提交表单之前或者你需要的地方需要把编辑器中编辑完的内容回写到你的表单字段中去,否则编辑结果没有保存写来就没有意义了。

基本原理就是这样。要做出这样一个东西来,需要的就是一些细活了。要想做出一个FCk这样好用的编辑器也不是那么简单的。但是至少我们知道它是怎么运作的。 这就够了。

花了点时间做了一个简单的编辑器,真正要用的话很多的细节还是需要好好处理的,代码没有怎么清理,是变想边写,不是很完整。

需要的同学可以下来参考参考。
猛击  >> 这里 << 下载代码。


  Tags: editor, html, JavaScript Category: JavaScript

新设计的博客首页

4 comments
Posted on 七 26 2009 by reeze

给自己的博客设计了一个新的界面,大概是定型了。。不想做了,明天还得上班,rblog还没有写好,不知道什么时候我的个人网站能上线啊。。

UPDATE: 最近太忙了,做好了以后都没有时间切图生产页面,让Tina同学帮我做好了都没时间做成皮肤。懒啊。。

home


Category: 乱78糟

基于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-&gt;_var = $var;
}
1
2
3
4
5
6
7
8
9
10
public function show()
{
echo $this-&gt;_var;
}
}

$string = "It's a string...";
$array = array(1, 2, 'key' =&gt; '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 =&gt; $value) {
$code .= "'$key'=&gt;".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
« Older Entries

最近文章

  • 解决Mac下终端中使用screen管理回话但看不到滚动条等问题
  • 让你的网站也像Gmail一样支持文件拖放上传-HTML5之File API
  • 开启Mac OS X Snow Leopard的NTFS原生读写
  • 在2009的尾巴上
  • 支持IPv6的Tunnelblick For Mac OS X OpenVPN客户端

分类目录

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

标签~云

2009 debug editor exception File API Gmail html HTML5 JavaScript linux Mac MacFUSE MacOSX NTFS OS X PHP screen screenrc Snow Leopard softwares ssh syntax check Tools VPN 托放上传

一些脚印

  • L42y 在 Lockerz邀请 上的评论
  • cloudshadow 在 Lockerz邀请 上的评论
  • reeze 在 让你的网站也像Gmail一样支持文件拖放上传-HTML5之File API 上的评论
  • bin 在 让你的网站也像Gmail一样支持文件拖放上传-HTML5之File API 上的评论
  • jumkey 在 让你的网站也像Gmail一样支持文件拖放上传-HTML5之File API 上的评论

Google Reader

  • 且听疯吟 » 如果爆炸不会骗人,那么是谁在说谎? (FeedzShare)
  • 无敌猫咪强大字幕组图(23P) (FeedzShare)
  • 南京城北化工厂爆炸,幸存者在人人上的日志…… http://sinaurl.cn/Gx9NZ (玩聚SR|最新)
  • 北韩政府官方网站那是很强强强强强强强强强强强大 (Initiative)
  • 强拆下的悲剧——村长许坤被施酷刑 (政府丑闻)
Shared Items

日志存档

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

链接表

  • Ideawu
  • LinuxToy
  • on Github
  • Tina的设计天地
  • 风雪之隅
想读
乐者为王
Pro Python System Administration
C专家编程
把妹达人-從宅男到型男之路
C语言程序设计:现代方法(第2版)
正读
建筑的永恒之道
亲密行为
裸猿三部曲:人类动物园
裸猿三部曲:裸猿
Clean Code
读过
我的奋斗
无懈可击的Web设计
应用Rails进行敏捷Web开发
追风筝的人
构建可扩展的Web站点

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