。。唱得真好
Monthly Archive for 二月, 2010
在Longbill同学那里看到的,这方法用得很巧,但可能不适用于国内某些虚拟主机环境下。
原理就是在session_start()之前,调用session_id(“xxxx”),手工指定session_id的值,这样以来,发送到客户端的PHPSESSID的cookie的值就一样了,这样每个客户端的session_id被手工指定为同一个。
这篇日志写得有点火星了。但从亲眼目睹了那场比赛,至今记忆犹新,感触深刻,心中的信念更是进一步加深。庞清、佟健追逐着他们不可能完成的梦,十几年来未曾放弃,追梦无悔的他们,最终完美的演绎了《Impossible Dream》。既然有梦想,那便努力去追逐,纵容还未达成,失败过了,却又何能停止我沸腾的血液和我继续追逐的脚步?
(以下来自央视)
当我们一直在嘲笑唐吉歌德,认为他是个疯子和傻子的同时,可曾想到追逐梦想的人,他们这种永不言败的精神才是我们最缺失的。那些永远无悔于自己的追求,即使是不可实现的梦,这是让人永远肃然起敬的。庞清佟健这对已过而立之年的老将,永远活在里程碑式的申赵组合阴影下,也许她们的技术不是最完美和高难的,没有最好的艺术修养和王者风范。但她们永远拥有一个梦想,她们为梦想而战,无怨无悔的承受着难以承受的伤痛,走向那条不归路,直到摘取梦想中的那颗星。
她们的表现告诉我们,只要你有梦想,只要你肯承受为梦想付出的一起代价和伤痛,只要你执着于自己的追求,即使那个梦想遥不可及,我们将摘取那颗星,即使失败也将无悔。无论成败,直到生命的终点,这才是人生的真谛。
要做那不可能实现的梦。
对抗无法匹敌的对手。
承受难以承受的悲痛。
去往勇者以畏惧之地。
纠正那无法改正的错误。
成为远远超越自己的人。
即使双臂疲惫不堪,仍要尽力去尝试。
要摘下那遥不可及的星星。这是我的追求,
去追随那颗星,
不管多么绝望,
不管多么遥远。毫不犹豫的为梦想而战,
即使向地狱进发也毫不退缩。而我明白只有
坚守着这光荣的使命,
闭上双眼,
内心必能得到安宁与平静。世界也将因此而更加美好。
无所畏惧,带着伤疤的人,
将战斗到最后,
直到摘到梦想中的那颗星。
知道173123.cn为什么有那么多丰富的ajax特效吗,这自然离不开jQuery的功劳哇。比如下面这段代码,用于提示“支持成功”、“反对成功”..
function showtip(msg){
tooltip = "
"+msg+"
";
$("body").append(tooltip);
$("div.tooltip").css({
'top':y+3+'px',
'left':x+3+'px',
'position':'absolute',
'border':'1px solid #2D2B28',
'padding':'5px 10px',
'background':'#6882B9',
'opacity':'0.8'
}).show("fast");
setTimeout(removeTip,1000);
function removeTip(){
$("div.tooltip").fadeOut();
}
}
——XXTEA 算法很安全,而且非常快速,非常适合应用于 Web 开发中。
今天在国内的一个前辈博客当中看到XXTEA的各种实现方法,有python/ruby/javascript等。原文参见http://www.coolcode.org/?action=show&id=128 而我打算用这个算法来加密一些Cookie数据,因此进行了小部分修改,增加了加密数组的功能(原理很简单 大家看代码),代码如下:
/**
* @author Ma Bingyao
* @copyright Ma Bingyao
* @package XXTEA encryption arithmetic library
* @version 1.5
* @lastupdate 2006-12-17
* @link http://www.coolcode.cn/?p=128
*/
Class Xxtea {
public function encrypt($s,$key){
is_array($s) && $s = serialize($s);
return str_replace(array('+','/','='), array('-','_','.'), base64_encode($this->xxtea_encrypt($s, $key)));
}
public function decrypt($e,$key,$isArray=false){
$c = str_replace(array('-','_','.'), array('+','/','='), $e);
if($isArray === false){
return $this->xxtea_decrypt(base64_decode($c), $key);
}else{
return unserialize($this->xxtea_decrypt(base64_decode($c), $key));
}
}
private function long2str($v, $w) {
$len = count($v);
$n = ($len - 1) << 2;
if ($w) {
$m = $v[$len - 1];
if (($m < $n - 3) || ($m > $n)) return false;
$n = $m;
}
$s = array();
for ($i = 0; $i < $len; $i++) {
$s[$i] = pack("V", $v[$i]);
}
if ($w) {
return substr(join('', $s), 0, $n);
} else {
return join('', $s);
}
}
private function str2long($s, $w) {
$v = unpack("V*", $s. str_repeat("\0", (4 - strlen($s) % 4) & 3));
$v = array_values($v);
if ($w) {
$v[count($v)] = strlen($s);
}
return $v;
}
private function int32($n) {
while ($n >= 2147483648) $n -= 4294967296;
while ($n <= -2147483649) $n += 4294967296;
return (int)$n;
}
private function xxtea_encrypt($str, $key) {
if ($str == "") {
return "";
}
$v = $this->str2long($str, true);
$k = $this->str2long($key, false);
if (count($k) < 4) {
for ($i = count($k); $i < 4; $i++) {
$k[$i] = 0;
}
}
$n = count($v) - 1;
$z = $v[$n];
$y = $v[0];
$delta = 0x9E3779B9;
$q = floor(6 + 52 / ($n + 1));
$sum = 0;
while (0 < $q--) {
$sum = $this->int32($sum + $delta);
$e = $sum >> 2 & 3;
for ($p = 0; $p < $n; $p++) {
$y = $v[$p + 1];
$mx = $this->int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ $this->int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
$z = $v[$p] = $this->int32($v[$p] + $mx);
}
$y = $v[0];
$mx = $this->int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ $this->int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
$z = $v[$n] = $this->int32($v[$n] + $mx);
}
return $this->long2str($v, false);
}
private function xxtea_decrypt($str, $key) {
if ($str == "") {
return "";
}
$v = $this->str2long($str, false);
$k = $this->str2long($key, false);
if (count($k) < 4) {
for ($i = count($k); $i < 4; $i++) {
$k[$i] = 0;
}
}
$n = count($v) - 1;
$z = $v[$n];
$y = $v[0];
$delta = 0x9E3779B9;
$q = floor(6 + 52 / ($n + 1));
$sum = $this->int32($q * $delta);
while ($sum != 0) {
$e = $sum >> 2 & 3;
for ($p = $n; $p > 0; $p--) {
$z = $v[$p - 1];
$mx = $this->int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ $this->int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
$y = $v[$p] = $this->int32($v[$p] - $mx);
}
$z = $v[$n];
$mx = $this->int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ $this->int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
$y = $v[0] = $this->int32($v[0] - $mx);
$sum = $this->int32($sum - $delta);
}
return $this->long2str($v, true);
}
}
继续说缓存,从缓存对象来看,第一种缓存技术缓存了页面片段,难免造成缓存的对象比较臃肿,于是便有人把程序中的变量(也许经过序列化),通过fwrite()或者file_put_contents()写入到文件中,同样通过设定过期时间来确保缓存的有效性,此外还引人了主动缓存和被动缓存的概念(如discuz所见)。此方法避免使用ob系列函数,提升了部分效率,特别是在虚拟主机下。其实现方法如下,转自一国产框架:
/**
* Punny - The most easy-to-use PHP MVC framework
* http://punny.skiyo.cn/
*
* Copyright (c) 2009 Jessica(董立强)
* Licensed under the MIT license.
*
* @author Jessica
* @version $Id: FileCache.class.php 267 2010-01-19 07:21:08Z jessica.dlq $
*/
class FileCache {
/**
* 缓存目录
*
* @var string
* @access private
*/
private $dir;
/**
* 构造器
*
* @access public
*/
public function __construct() {
$this->dir = 'cache/'; //缓存目录
@chmod($this->dir, 0777);
if(!is_writable($this->dir)) {
throw new Exception('缓存文件夹' . $this->dir . '不可写!');
}
}
/**
* 设置一个缓存变量
*
* @param String $key 缓存Key
* @param mixed $value 缓存内容
* @param int $expire 缓存时间(秒)
* @return boolean 是否缓存成功
* @access public
* @abstract
*/
public function set($key, $value, $expire = 60) {
$file = $this->dir . md5($key) . '.cache';
if(file_put_contents($file , serialize($value), LOCK_EX)) {
@touch($file, time() + $expire);
return true;
} else {
return false;
}
}
/**
* 获取一个已经缓存的变量
*
* @param String $key 缓存Key
* @return mixed 缓存内容
* @access public
*/
public function get($key) {
$file = $this->dir . md5($key) . '.cache';
if(is_file($file)) {
if(time() <= filemtime($file)) {
return unserialize(file_get_contents($file));
} else {
@unlink($file);
//删除缓存
return false;
}
} else {
//没有找到缓存
return false;
}
}
/**
* 删除一个已经缓存的变量
*
* @param $key
* @return boolean 是否删除成功
* @access public
*/
public function del($key) {
$file = $this->dir . md5($key) . '.cache';
return @unlink($file);
}
/**
* 删除全部缓存变量
*
* @return boolean 是否删除成功
* @access public
*/
public function delAll() {
$files = scandir($this->dir);
$files = array_diff($files, array('.', '..'));
foreach($files as $file) {
@unlink($file);
}
return true;
}
/**
* 检测是否存在对应的缓存
*
* @param string $key 缓存Key
* @return boolean 是否存在key
* @access public
*/
public function has($key) {
return (is_file($this->dir . md5($key) . '.cache') === NULL ? false : true);
}
}
(有标题党嫌疑)
正在为173123.cn设计一套缓存机制,将讲所用到的知识在这里总结一下:
在我目前看来,PHP目前常用的缓存技术分为三类,大致上通过缓存数据或者代码,减少了数据库查询次数或者资源初始化次数。
第一类是Smarty等模板引擎生成静态页时采用的ob系列函数(ob_start()、ob_get_contents、flush()等),将页面要缓存的部分通过缓存在缓冲区(*通常还要进一步进行serialize之后保存在文本文件中,每个页面以文件名为$_SERVER['SCRIPT_URI']的独立文件区分),其实现和使用方法大致如下:
require ('cache.class.php');
$cache = new cache('cache/cache_name.php',60*30); //可自定义缓存文件名和过期时间
$cache->start(); //开始加载缓存 如果存在缓存并且还未国企 则自动include缓存内容
# 你的页面内容
$cache->end();
class cache {
public $_file;
public $cache_time;
function cache($_file='_index.htm',$cache_time=1) {
$this->_file = $_file;
$this->cache_time = $cache_time;
}
/*
* Start cache method without Return
*/
function start() {
if($this->cache_is_active()) {
include($this->_file);
exit;
}
ob_start();
}
/*
* End of cache method without Return
*/
function end() {
$this->make_cache();
ob_end_flush();
}
/*
* Check if cache file is actived
* Return true/false
*/
function cache_is_active() {
if ($this->cache_is_exist()) {
if (time() - $this->lastModified() < $this->cache_time)
Return true;
else {
Return false;
}
}
else {
Return false;
}
}
/*
* Create cache file
* Return true/false
*/
function make_cache() {
$content = $this->get_cache_content();
if($this->write_file($content)) {
Return true;
}
else {
Return false;
}
}
/*
* Check if cache file is exists
* Return true/false
*/
function cache_is_exist() {
if(file_exists($this->_file)) {
Return true;
}
else {
Return false;
}
}
/*
* Return last Modified time in bollin formart
* Usage: $lastmodified = $this->lastModified();
*/
function lastModified() {
Return @filemtime($this->_file);
}
/*
* Return Content of Page
* Usage: $content = $this->get_cache_content();
*/
function get_cache_content() {
$contents = ob_get_contents();
// Return ''.$contents;
Return $contents;
}
/*Write content to $this->_file
* Return true/false
* Usage: $this->write_file($content);
**/
function write_file($content,$mode='w+')
{
$this->mk_dir($this->_file);
if (!$fp = @fopen($this->_file,$mode)) {
$this->report_Error($this->_file." 目录或者文件属性无法写入.");
Return false;
} else{
@fwrite($fp,$content);
@fclose($fp);
@umask($oldmask);
Return true;
}
}
/*
* Make given dir included in $this->_file
* Without Return
* Usage: $this->mk_dir();
*/
function mk_dir()
{ //$this->_file = str_replace('','/');
$dir = @explode("/", $this->_file);
$num = @count($dir)-1;
$tmp = './';
for($i=0; $i<$num; $i++){
$tmp .= $dir[$i];
if(!file_exists($tmp)){
@mkdir($tmp);
@chmod($tmp, 0777);
}
$tmp .= '/';
}
}
/*
* Unlink an exists cache
* Return true/false
* Usage: $this->clear_cache();
*/
function clear_cache() {
if (!@unlink($this->_file)) {
$this->report_Error('Unable to remove cache');
Return false;
}
else {
Return true;
}
}
/*
* Report Error Messages
* Usage: $this->report_Error($message);
*/
function report_Error($message=NULL) {
if($message!=NULL) {
trigger_error($message);
}
}
}
这个博客几天前刚刚搭建起来,我想也没有人会看到这个名不见经传的小谢的博客吧~但我还是不免要怀着一颗媚俗的心,对自己,对博客将来的访问者,说一声新年快乐~这逻辑似乎不大对,傻里傻气的,似乎是受了最近看的《天龙八部》里段誉言行的影响,啊哈哈哈。。
新的一年要有新气象。今年一年,最重要的是得注意转变自己的心态了。毕竟即将毕业了,一份成熟的心态对以后的工作和发展都是大有裨益的。我希望自己能够在下半年顺利走上职场,为此,我得做好充分的准备:无论是思想上,还是在专业技术上。思想上主要表现为全面、周到的思考方式和妥善的问题处理方法,考虑到自己思想上还比较孩子气,我想得花很多时间在提高自己的思想境界上,我必须要有强烈的上进心;技术上的追求主要还是要由求知欲驱动,在这青涩、迷茫无措、看不到未来的时候,我还是信奉“兴趣就是天赋 天赋就是兴趣”的金字箴言,为了自己想要的生活,为了自己未竟的事业,追随我心,朝着目标步步迈进!
鹏腾哥说得对,在当今竞争激烈的社会,只有适者才能生存;不是谁都能碰上好运气,要踏踏实实从底层做起,只要有头脑和上进心,总有守得云开见月明的时候。
最后,借用一下勾践灭吴的典故,以勉励自己:
有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
今天在做网站框架的View部分的时候,要对于安的phpnew模板引擎进行改造,要实现如下三种变量注入方式:
$array1 = array(
'0' => $subarray1(...),
'1' => $subarray2(...)
);
$array2 = array(
'title'=>'aaaaa',
'content'=>'asdffsdas'
);
$this->display('index',$array1); //多维数组 用于直接循环输出
$this->display('index','name',$value);//普通变量赋值
$this->display('index',$array2); //支持数组解析
而phpnew只支持两种变量注入
$tpl->assign('tpl','footer'); //变量注入
$tpl->assign(array('abc'=>'str','str'=>'php')); //数组解析
最终实现,是用到了获取变量名的方法
/**
* 获取变量名
*
* @param $string
* @return $string
*
* $test = "helo";
* $test2 = "helo";
* getVarName($test2);
*/
function getVarName(&$src){
//存储当前变量值
$save = $src;
//存储所有变量值
$allvar = $GLOBALS;
//在函数中不要直拉遍历$GLOBALS,会出现堆栈问题
foreach($allvar as $k=>$v){
//变量值相同,可能不是相同变量,因多个变量的值可能相同
if ($src == $v){
//改变当前变量$src的值
$src = 'change';
//如果$GLOBALS[$k]也跟着改变,那就是同一个变量。
if ($src == $GLOBALS[$k]){
//echo "\$$k name is $k
";
//还原变量值
$src = $save;
return $k;
}
}
}
}
参考http://blog.csdn.net/johnpanq/archive/2005/12/15/553328.aspx

Facebook神秘的PHP项目HipHop for PHP终于揭开面纱。这个项目由一个PHP到C++的转换程序,一个重新实现的PHP运行库,和许多常用PHP扩展的重写版本构成,目的是旨在加速和优化PHP。
用Facebook官方博客(无法直接访问)上项目负责人赵海平(北大1987届遗传与分子生物专业,普林斯顿计算机科学博士)的话说,HipHop项目对Facebook影响巨大。它目前已经支撑了Facebook 90%的Web流量。由于HipHop,Facebook Web服务器上的CPU使用平均减少了50%,从而大大减少了服务器的需求。为了让这一改进也惠及社区,他们决定将之开源,希望能够进一步帮助提高更多大型复杂PHP网站的可伸缩性。

PHP和Facebook的问题
众所周知,Facebook的前端主要是用PHP写的。赵海平说,过去六年Facebook从PHP语言的进展上获益良多。PHP非常简单,易学易用,好读好调试,因此新工程师成长很快,有利地促进了Facebook的更快的创新。
PHP是一种脚本语言,其好处是编程效率高,能够支持产品的快速迭代。但是与传统的编译语言相比,脚本语言的CPU和内存使用效率不好。随着Ajax技术的广泛采用,加上SNS对动态要求较高,这些缺点更显得突出。对于每月超过4000亿次PV的Facebook来说,如何实现扩展,尤其具有挑战性。
常见的办法是直接用C++重写PHP应用中比较复杂的部分,作为PHP扩展。实际上,PHP就转变为一种胶水语言,连接前端HTML和C++应用逻辑。从技术角度讲这也没有问题,但是增加了技能需求,能够在整个应用上工作的工程师数量就大大减少了。学习C++只是编写PHP扩展的第一步,接下来还要理解Zend API。由于Facebook的工程团队较小,每个工程师要支持100万以上的用户。有些代码不是团队里每个人都能看懂,这对于Facebook是无法接受的。
Facebook网站本身的可伸缩性更具挑战性,因为几乎每次页面浏览都是有个性化体验的登录用户发起。浏览主页 时,系统需要查询所有朋友、朋友最重要的状态更新、 根据隐私设置筛选结果,然后还要显示评论、照片等等动态,这一切都需要在一秒内完 成。
自2007年以来,Facebook曾写过几种不同办法解决这些问题。其中包括用另 一种语言重写Facebook,但是由于开发的复杂性和速度等原因,未能实现。他们还重写了PHP的核心部分Zend引擎,并提交给了PHP项目,但最终还是没有获得所需的性能。最后,他们选择了HipHop,终于得偿所愿。
有了HipHop,工程师可以编写代码,用PHP编写组合最后页面的逻辑,并能够继续快速迭代,同时后端服务使用C++, Erlang, Java, Py thon编写,提供新闻提要、搜索、聊天和其他核心功能。
HipHop开发故事
赵海平透露,项目最初是来自几年前Facebook公司一次Hackathon活动(员工在一个晚上自由发挥,实验新的想法),他手工将PHP转换为C++代码,虽然语法上很类似,但是无论是CPU还是内存使用,转换后的C++代码都大大优于PHP。于是他想,如果构建一个系统,编程实现转换,会怎么样呢?
在此之前,已经有了不少改善PHP性能的方法。Zend引擎在运行时转换PHP源代码为运行在Zend虚拟机上的opcode。开源项目APC和eAccelerator将输出缓存,为大多数PHP网站所使用。此外,还有Zend Server这样的商业产品,通过opcode优化和缓存,提高PHP速度。赵海平选择了另一条道路,将PHP直接转为C++,然后再变成本地机器码。当然,有许多开源项目也是同样的思路,Roadsend和phc编译为C,Quercus编译为Java,而Phalanger编译为.NET。
Hackathon之后8个月,赵海平拿出了原型,足以说明这条路可以走通,编译后的代码的确更快。不久,Iain Proctor和Minghui Yang加入进来。接下来又开发了10个月,在生产服务器上测试了6个月。然后正式上线部署,6个月之后,Facebook 90%以上的Web流量都使用了HipHop。
按赵海平的说法,凭借HipHop,Facebook Web服务器上的CPU使用平均减少了50%,从而大大减少了服务器的需求。项目对Facebook影响巨大。为了让这一改进也惠及社区,他们决定将之开源,希望能够进一步帮助提高更多大型复杂PHP网站的可伸缩性。
HipHop的原理
HipHop将PHP代码转换为高度优化的C++代码,然后再用g++编译器编译。它可以保持语义等效地执行源代码,但为了提高性能,牺牲了一些很少用到的特性,比如eval()。
HipHop开发中的主要困难在于,在PHP和C++这两种很不一样的语言之间怎么实现转换。虽然PHP也可以写一些很巧妙的动态特性,但是大多数PHP代码还是非常简单的。if (…) {…} else {..} 比foo($x) { include $x; } 肯定更常见。这为性能提高提供了机会。HipHop生成的代码尽可能地使用函数和变量的静态绑定。同时,还使用类型推演来选出变量最可能对应的某个类型,从而节省内存。
转换过程分三步:
1. 静态分析。收集声明关系和依赖关系等信息。
2. 类型推演。选择最合适的类型,是C++的标量?还是String, Array, classes, Object或者Variant。
3. 代码生成。大部分直接将PHP语句和表达式对应为C++的语句和表达式。
在开发过程中,还有一个副产品:HPHPi,是一个实验性的解释器。通过它,不编译PHP源代码也可以运行。它已经用于HipHop自身的调试中。
HipHop在保持了PHP优点的同时,也兼得了C++的性能优势。项目总共有30万行代码,5000多个单元测试。所有这些都将以PHP开源许可证形式发布到GitHub。
更多信息,可以申请加入HipHop的邮件列表:
近期评论