Archives

Archive for July, 2007

Fanfou Logo

这次直接升级到 1.00 stable,终结该死的 beta version。

感谢 72pines 提供的 mo/po 翻译文件,Fanfou Tools 现在有了中文版本。
如果您在使用的过程中,仍然显示为英文界面,打开 wp-config.php 文件,修改如下代码:

// Change this to localize WordPress.  A corresponding MO file for the
// chosen language must be installed to wp-includes/languages.
// For example, install de.mo to wp-includes/languages and set WPLANG to 'de'
// to enable German language support.
define ('WPLANG', 'zh_CN');

fanfou tools 已经加入官方的 Plugins 列表:

http://wordpress.org/extend/plugins/fanfou-tools/

如果您有 SVN 客户端软件,也可以从 SVN 上下载最新的代码:

svn co http://svn.wp-plugins.org/fanfou-tools/trunk

详细信息、下载,请访问:
WordPress Plugin – Fanfou Tools

Comments Off on WordPress Plugin – Fanfou Tools 1.00 (stable version)
Jul 31st, 2007 | Filed under WordPress

PHP6 的 snapshot 版本中,namespace 功能已经实现了,下面我们就通过几个简单的示例来介绍一下,如何在 PHP6 中使用 namespace。

一、如何定义 namespace?

// net/phpvim/code/Shape.php
namespace net::phpvim::code;
 
class Shape{
}
 
function draw() {
    return "draw() in Shape.php\n";
}
 
function getCurrentNS() {
    return __NAMESPACE__;
}
 
/* vim: set expandtab tabstop=4 shiftwidth=4: */

所有的类和函数名称会自动加上 namespace 名称作为前缀,相同的 namespace 也可以在多个 PHP 文件中被定义。

比如上面的代码中,完整的类名和函数名是:

net::phpvim::code::Shape
net::phpvim::code::draw()

二、如何使用呢?

// net/phpvim.net/code/Painter.php
require_once 'net/phpvim/code/Shape.php';
 
import net::phpvim::code;
import net::phpvim::code::Shape;
import net::phpvim::code::Shape as CPC_Shape;
 
// Create an instance object for Shape class
$shape0 = new net::phpvim::code::Shape();
$shape1 = new code::Shape();
$shape2 = new Shape();
$shape3 = new CPC_Shape();
 
// output: draw() in Shape.php
print net::phpvim::code::draw();
print code::draw();
 
// output: net::phpvim::code
print code::getCurrentNS();
 
/* vim: set expandtab tabstop=4 shiftwidth=4: */
</php>
 
import 指令
 
import 可以将任意的 package(这里借用一下 Java 的概念)导入到当前 scope 中来。
import 不可以使用在函数或者类中。
import 生效范围为当前定义位置到所在文件的结尾。
import 可以通过 AS 关键字定义别名。
import A::B; 等同于 import A::B as B。
 
 
<strong>三、其它</strong>
特殊的 empty namespace ::
 
<pre lang="php">
import net::phpvim::code;
echo ::draw();
/* vim: set expandtab tabstop=4 shiftwidth=4: */

:: 是一个特殊的 namespace,以 :: 开头的调用,将会在 global 范围查找并绑定相应的 Class 或者 Function。换句话说,定义在任意 namespace 中的 draw() 函数都不会被调用,而是调用 global 范围内的 draw() 函数。

constant __NAMESPACE__

__NAMESPACE__ 表示当前的 namespace 的名称。

Jul 22nd, 2007 | Filed under PHP
Tags: ,

Fanfou Logo

Fanfou Tools 更新到 v1.0b7,这次增加了一个好友模块,可以在侧边栏中显示饭否的好友头像。

增加了显示好友数目的设置选项,还有 Widgets 中可以自己设定模块的标题了。

增加了一个 UBB 标签:[tiny][/tiny],在 Write Fanfou 时,使用这个标签就可以把很长的 URL 转换为较为短小的 TinyURL。

PS: Fanfou Tools 已经提交到了 WordPress 官方插件网站,希望能够审核通过。

详细信息、下载,请访问:
WordPress Plugin – Fanfou Tools

Comments Off on WordPress Plugin – Fanfou Tools 1.0 Beta 7
Jul 19th, 2007 | Filed under WordPress

什么是多态性?
多态性是继数据抽象和继承后,面向对象语言的第三个特征。从字面上理解,多态的意思是“多种形态”,简单来说,多态是具有表现多种形态的能力的特征,在OO中是指“语言具有根据对象的类型以不同方式处理之,特别是重载方法和继承类这种形式”的能力。多态被认为是面向对象语言的必备特性。

例如:
我们创建一个接口 Shape,定义一个空的方法 draw(),那么所有的实现类都必须实现这个方法,假设 Shape 有两个实现类:Triangle 和 Rectangle,我们虽然无法通过类似这样的 Java 代码来诠释 PHP 的多态性:

1
2
Shape s = new Triangle();
s.draw();

不过 PHP5.1 中引入了 Type Hinting,可以限制函数(或者方法)的参数类型,我们使用这个特性来演示 PHP5 的多态性。

参考如下的代码:

1
2
3
4
5
class TestPolymorphism {
    public function drawNow(Shape $shape) {
        $shape->draw();
    }
}

函数 drawNow() 中限制传入的参数类型必须为 Shape 接口派生类的对象,这里我们传递给 drawNow() 的参数可能是 Triangle 或者 Rectangle 的对象,也可能是其它的 Shape 接口的派生类对象,比如 Circle 等等,简单的说 drawNow() 的参数类型是无法预知的,$shape->draw() 的行为最终由传入的参数的具体类型来决定,比如如果传入 Triangle 的对象,那么就调用 Triangle 的 draw() 方法,如果传入 Rectangle 的对象,就调用 Rectangle 的 draw() 方法。这种在运行时刻根据传递的对象参数的类型来决定调用哪一个对象的方法的行为就可以称之为多态。

Shape 也可以是一个抽象基类或者是非抽象的基类,上面的论述都是成立的。区别在于接口仅定义一套实现类必须遵守的规则,而使用基类则可以为派生类提供一些缺省的行为。

参考代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/**
 * Shape Interface
 * 
 * @version 1.0
 * @copyright 
 */
interface Shape {
    public function draw();
}
 
/**
 * Triangle 
 * 
 * @uses Shape
 * @version 1.0
 * @copyright
 */
class Triangle implements Shape {   
    public function draw() {
        print "Triangle::draw()\n";
    }
}
 
/**
 * Rectangle 
 * 
 * @uses Shape
 * @version 1.0
 * @copyright
 */
class Rectangle implements Shape {
    public function draw() {
        print "Rectangle::draw()\n";
    }
}
 
/**
 * Test Polymorphism
 * 
 * @version 1.0
 * @copyright
 */
class TestPoly {
    public function drawNow(Shape $shape) {
        $shape->draw();
    }
}
 
 
$test = new TestPoly();
$test->drawNow(new Triangle());
$test->drawNow(new Rectangle());
 
/* vim: set expandtab tabstop=4 shiftwidth=4: */

什么是动态绑定?
HaoHappy 翻译的 PHP5 Object Pattern 第九节中有介绍:

除了限制访问,访问方式也决定哪个方法将被子类调用或哪个属性将被子类访问。 函数调用与函数本身的关联,以及成员访问与变量内存地址间的关系,称为绑定。

另有的说法:

绑定(binding):将方法的调用连到方法本身被称为绑定,当绑定发生在编译期,被称做静态绑定,而在程序运行的时候根据对象的类型来决定该绑定方法的成为动态绑定。

PHP 是一种动态语言,使用动态绑定。无须考虑采取何种绑定策略,因为一起都是自动的。

(待续…)

😳

Jul 18th, 2007 | Filed under PHP
Tags: ,

之前一直无法将 5 种 Interfaces(Perl, Python, Ruby, Tcl, MzScheme) 全部编译进去,ex_docmd.c 有 bug,不过已经 7.1.029 中已经修正了这个问题。

Python 也升级到了 Python 2.5,不再使用 2.4,使用了几个 Python 编写的插件,都没什么问题。

以下是最新的五个补丁信息 ( http://ftp.vim.org/vim/patches/7.1/ ):

2239 7.1.028 “:sort” does nothing special with empty search pattern
2692 7.1.029 (after 7.1.019) can’t compile when all interfaces are used
2364 7.1.030 vimtutor shell script checks for “vim6” but not for “vim7”
6533 7.1.031 virtcol([123, ‘$’]) doesn’t work
3006 7.1.032 possible crash when doing completion on the command line

Detail:
http://www.phpvim.net/vim/my-build-vim-executables.html

Download:
http://www.phpvim.net/files/vim/vim71-latest.7z

Comments Off on Vi IMproved 7.1.32 – Included patches: 1-32
Jul 18th, 2007 | Filed under Vim
Tags:

大部分情况下我们都是通过Windows自带的环境变量编辑器来修改系统环境变量,也可以通过Windows系统提供的path,set两个命令临时修改。

使用系统编辑器修改环境变量最终会反映到注册表中保存,我们知道环境变量分为两种,用户变量,以及系统变量,其存储的位置分别位于:

系统变量:

1
2
3
[HKLM\SYSTEM\ControlSet001\Control\Session Manager\Environment] 
[HKLM\SYSTEM\ControlSet002\Control\Session Manager\Environment] 
[HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment]

用户变量:

1
[HKCU\Environment]

其中HKLM = HKEY_LOCAL_MACHINE,HKCU = HKEY_CURRENT_USER

ControlSet001/ControlSet002/CurrentControlSet 保存用于系统启动的重要配置信息,其中 CurrentControlSet 指向 ControlSet001 ,两者互相同步,每次针对两者中任意一个分支的修改都会立即复制到另外一个分支相对应的键值中。

当系统启动时,会使用其中一个分支的信息以尝试启动系统,这个就是 ControlSet001,如果启动成功,那么 ControlSet001 的信息会复制到 ControlSet002 中。如果启动失败,那么就不会发生这个复制过程。

当系统因某些原因无法启动时,我们通常会使用 “Using the Last Known Good Configuration” 来尝试启动系统,也就是“最后一次正确的配置”(启动时按住F8),这时系统使用的就是ControlSet002 分支的配置信息。

上面仅针对 Windows XP,其它版本的 Windows 系统应该都是类似的。

由于我编译 VI IMproved 每次都要为 Make_cyg.mak 设置环境变量,非常的麻烦,所以就查找了这方面的知识,把设置 Environment 的过程写入注册表文件中,每次只要导入即可,非常的方便。

如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Windows Registry Editor Version 5.00
 
[HKEY_CURRENT_USER\Environment]
 
"PERL"="C:/Perl"
"PERL_VER"="58"
"DYNAMIC_PERL"="yes"
 
"PYTHON"="C:/Python25"
"PYTHON_VER"="25"
"DYNAMIC_PYTHON"="yes"
 
"RUBY"="C:/Ruby"
"RUBY_VER"="18"
"RUBY_VER_LONG"="1.8"
"DYNAMIC_RUBY"="yes"
 
"TCL"="C:/Tcl"
"TCL_VER"="84"
"DYNAMIC_TCL"="yes"
 
"MZSCHEME"="C:/MzScheme"
"MZSCHEME_VER"="370_000"
"DYNAMIC_MZSCHEME"="yes"
Comments Off on 通过注册表设置环境变量
Jul 18th, 2007 | Filed under Windows
Tags:

最近一直在准备面试的东西,看到这样一个问题:你的理想是什么?

没工作的这些日子发生了很多事情,烦闷之余,我常常会考虑这个问题,我的将来会是怎样的?我的理想到底什么?小时候曾想过当个小说家,那时候自己还是蛮喜欢写作的。后来接触了电脑,想过做一个程序员,于是我真的成了一个程序员(插播小广告:要雇用我吗?),这个工作一做就是7、8年,不过这个该死的行当给我带来的只有辛酸。

撇开那些不谈,我这个人不太喜欢旅行,可是却有一个几乎所有人都有的理想:周游世界。你也有,是不是?可惜!真正能实现的人少之又少,人们总会被这样那样的原因所羁绊。目前我还属于理想未遂的那种,呵呵!我没钱,所以只能窝在屏幕前,顺着网线魂游世界,一天天浑噩颓废的生活最终磨穿了理想的翅膀,理想飞走了,我他妈地还在网上爬……

《美国空姐》里面有一段话说:我不想让别人告诉我世界是怎样的。虽然她最终选择了爱情,但是,她为了理想曾拚尽全力,成功过。最终她明白的是,再美丽的风景没有爱人在身边也会变得空洞、令人厌烦。

和爱人一同游遍世界,是件多幸福的事啊!

PS: 写了个小插件 Wisdom 放点名言啥的,时时刻刻提醒自己,做人要有理想,否则就成咸鱼一条了 :)

Comments Off on 你的梦想是什么?
Jul 9th, 2007 | Filed under Journal
Tags:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
 
/**
 * 将 %u4F19 转换成如 &#20249; 的 HTML Entity 的形式
 *
 * @param mixed $str
 * @access public
 * @return void
 */
function convert_entities($str) {
    $str = preg_replace_callback('|%u([a-f0-9]{4})|i',
        create_function(
            '$matches',
            'return \'&#\' . hexdec($matches[1]) . \';\';'
        ),
        $str
    );
    return $str;
}
 
 
/**
 * 把 HTML Entity 转换为原始字符
 *
 * @param mixed $source
 * @access public
 * @return void
 */
function utf8encode($source) {
    $utf8str  = '';
    $entities = explode('&#', $source);
    $size     = count($entities);
 
    for ($i = 0; $i < $size; $i++) {
        $foo       = $entities[$i];
        $nonEntity = strstr($foo, ';');
 
        if ($nonEntity !== false) {
            $unicode = intval(substr($foo, 0, (strpos($foo, ';') + 1)));
            // determine how many chars are needed to reprsent this unicode char
            if ($unicode < 128) {
                $bar = chr($unicode);
            }
            else if ($unicode >= 128 and $unicode < 2048) {
                $binVal   = str_pad(decbin($unicode), 11, '0', STR_PAD_LEFT);
                $binPart1 = substr($binVal, 0, 5);
                $binPart2 = substr($binVal, 5);
 
                $char1 = chr(192 + bindec($binPart1));
                $char2 = chr(128 + bindec($binPart2));
                $bar   = $char1 . $char2;
            }
            else if ($unicode >= 2048 and $unicode < 65536) {
                $binVal   = str_pad(decbin ($unicode), 16, '0', STR_PAD_LEFT);
                $binPart1 = substr($binVal, 0, 4);
                $binPart2 = substr($binVal, 4, 6);
                $binPart3 = substr($binVal, 10);
 
                $char1 = chr(224 + bindec($binPart1));
                $char2 = chr(128 + bindec($binPart2));
                $char3 = chr(128 + bindec($binPart3));
                $bar   = $char1 . $char2 . $char3;
            }
            else {
                $binVal   = str_pad(decbin($unicode), 21, '0', STR_PAD_LEFT);
                $binPart1 = substr($binVal, 0, 3);
                $binPart2 = substr($binVal, 3, 6);
                $binPart3 = substr($binVal, 9, 6);
                $binPart4 = substr($binVal, 15);
 
                $char1 = chr(240 + bindec($binPart1));
                $char2 = chr(128 + bindec($binPart2));
                $char3 = chr(128 + bindec($binPart3));
                $char4 = chr(128 + bindec($binPart4));
                $bar   = $char1 . $char2 . $char3 . $char4;
            }
 
            if (strlen($nonEntity) > 1) {
                $nonEntity = substr($nonEntity, 1); // chop the first char (';')
            }
            else {
                $nonEntity = '';
            }
            $utf8str .= $bar . $nonEntity;
        }
        else {
            $utf8str .= $foo;
        }
    }
    return $utf8str;
}
 
$str = '%u4F19%u8BA1';
$str = convert_entities($str);
print utf8encode($str);
// output: 伙计
Comments Off on Unicode encode :)
Jul 8th, 2007 | Filed under PHP
Tags: ,

Motivation
复杂的表达式是很难阅读的,不仅如此,很多时候由于表达式太长而不得不换行书写,也影响代码的美化。

比如 If 括号中的条件表达式,如果太长的话,我们可以把表达式拆分为几个小的表达式,并赋值给不同的临时变量,这样代码将会显得清晰美观,易于阅读。

Example Code

1
2
3
4
5
6
7
8
function price() {
    // price is base price - quantity discount + extra fee
    return $this->quantity * $this->item_price -
        max(0, $this->quantity - 200) * $this->item_price * 0.08 +
        min($this->quantity * $this->item_price * 0.1, 100.0);
}
 
/* vim: set expandtab tabstop=4 shiftwidth=4: */

是不是又臭又长很难读啊?下面我们试着把表达式拆分:

1
2
3
4
5
6
7
8
function price() {
    $price    = $this->quantity * $this->item_price;
    $discount = max(0, $this->quantity-200) * $this->item_price * 0.08;
    $fee      = min($basePrice * 0.1, 100.0);
    return  $price - $discount + $fee;
}
 
/* vim: set expandtab tabstop=4 shiftwidth=4: */

上面的重构的代码,已经达到了我们的目的,下面我们来尝试一下新的重构方式:Extract Methods,把表达式拆分为一个个小的函数(或方法)。

拆分成函数和拆分为变量可以达到相同的效果,但如果我们需要达到重用的效果,Extract Methods 更适合,再看下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function getPrice() {
    return  $this->price() - $this->discount() + $this->fee();
}
 
// Extract as methods
 
function price() {
    return $this->quantity * $this->item_price;
}
 
function discount() {
    return max(0, $this->quantity - 200) * $this->item_price * 0.08;
}
 
function fee() {
    return min($this->price() * 0.1, 100.0);
}
 
/* vim: set expandtab tabstop=4 shiftwidth=4: */

在这个例子中,Extract Methods 比 Explaining Variables 更好用,但并不代表所有的情况,还是那句话:具体问题具体分析。

使用哪种重构方法,还要看具体的情况而定。

Comments Off on Introduce Explaining Variable
Jul 5th, 2007 | Filed under PHP
Tags: ,

当一个临时变量被赋值多次时,那么将其拆分成多个,除非它是一个循环计数器。

Motivation

临时变量有这多种不同的用途。比如它们可被用作循环中的计数器,在循环中保存结果集,亦或保存一个冗长的表达式的计算结果等等。

这些类型的变量(容器)应该只赋值一次。如果一个同名的临时变量被赋予多个职责,将会影响代码的可读性。这个时候我们应当引入一个新的临时变量以使代码更加清晰易懂。

可能有些注重性能的人会说,引入一个新的变量将会占用更多的内存。的确如此,但是注册一个新的变量不会吸干服务器内存的,这一点请放心,我们不是活在 386 时代,与其在这些无聊的细枝末节上面搞所谓的优化,不如去优化真正的系统性能瓶颈,比如数据库、网络连接等等,而且清晰易懂的代码更容易被重构,发现 Bug,或者解决性能问题等等。

Example Code

很多时候,我们使用同一个 $temp 变量来计算一个物体的不同属性,这种情况比较常见,比如下面这个例子:

1
2
3
4
5
6
7
8
9
function rectangle($width=1, $height=1) {
    $temp = 2 * ($width + $height);
    echo "Perimter: $temp <br />";
 
    $temp = $width * $height;
    echo "Area: $temp";
}
 
/* vim: set expandtab tabstop=4 shiftwidth=4: */

正如你所看到的,$temp 被使用了两次分别用来计算长方形的周长以及面积。这个例子看起来非常直观清晰,但实际的项目代码可能远比这个例子复杂,如果我们把代码改成下面的样子,这样,不管代码如何复杂都不会有混淆感了。

1
2
3
4
5
6
7
8
9
function rectangle($width=1, $height=1) {
    $perimeter = 2 * ($width + $height);
    echo "Perimter: $perimeter <br />";   
 
    $area = $width * $height;
    echo "Area: $area";
}
 
/* vim: set expandtab tabstop=4 shiftwidth=4: */

为不同的东西(如表达式)声明一个新的临时变量吧,大部分时候性能并不是什么问题,而可读性则非常重要。

Comments Off on 拆分临时变量
Jul 5th, 2007 | Filed under PHP
Tags: ,