一些PHP Coding Tips (Laruence文章中自己平时没有注意到的地方)

2011年4月6日 2 条评论

读了Laruence的“一些PHP Coding Tips”这篇文章之后,发现自己有许多细节平时编程都没有注意到:

1. 使用NULL === 来代替is_null:
is_null和 NULL === 完全是一样的效果, 但是却节省了一次函数调用.

2. 使用===尽量不用==:
PHP有俩组相等比较运算符===/!==和==/!=, ==/!=会有隐式类型转换,而===/!==会严格比较俩个操作时是否类型相同并且值相等.
我们应该尽量使用===而不是==, 除了因为转换规则比较难记以外, 还有一点就是如果使用===, 对于日后的维护或者阅读你代码的人也会很舒服:”在这个时刻, 这一行语句, 这个变量就是这个类型的!”.

3. 少用/不用 continue:
continue是回到循环的头部, 而循环结束本来就是回到循环的头部, 所以通过适当的构造, 我们完全可以避免使用这条语句, 使得效率得到改善.

4. 警惕switch/in_array等的松比较(loose comparision):
switch和in_array都是采用松比较, 所以在要比较的变量之间类型不一样的时候, 很容易出错:
[php]
switch ($name) {
case "laruence":

break;
case "eve":

break;
}
[/php]
对于上面的switch, 如果$name是数字0, 那么它会满足任何一条case. 同理在in_array中也是.
解决的办法就是, 在switch之前, 把变量类型转换成你所期望的类型.
[php]
switch (strval($name)) {
case "laruence":

break;
case "eve":

break;
}
[/php]
而, in_array提供了第三个可选的参数, 通过这个参数可以改变默认的比较方式.

4. switch不仅仅只用来判别变量:
比如, 对于如下的一段代码:
[php]
if($a) {
} else if ($b) {
} else if ($c || $d) {
}
[/php]
可以简单的改写为:
[php]
switch (TRUE) {
case $a:
break;
case $b:
break;
case $c:
case $d:
break;
}
[/php]
是不是看起来更清晰呢?

5. 变量先定义后使用:
使用一个未定义的变量, 比使用一个定义好的变量要慢8倍以上!
可以相像, PHP引擎会首先按照正常的逻辑来获取这个变量, 然而这个变量不存在, 所以PHP引擎需要抛出一个NOTICE, 并且进入一段使用未定义变量时应该走的逻辑, 然后返回一个新的变量.
另外, 阅读代码的角度讲, 当你使用一个未定义的变量时, 会让阅读你代码的人困惑:”这个变量在那里初始化的, 和之前的代码有关系么? 和include进来的文件有关系么?”
最后, 从规范编程的角度来讲, 你也需要这样做.

6. 不用第三变量交换俩个变量的值:
[php]
list($a, $b) = array($b, $a),
[/php]
但其实还是有匿名临时变量的产生, 对于整数来说, 采用互逆的运算来做, 还是比较靠谱:
[php]
$a = $a + $b;
$b = $a – $b;
$a = $a – $b;
[/php]
不过, 还是用异或比较好, 因为+ – * /容易产生精度丢失或者溢出.

7. floor == 俩次非运算(此条由skiyo提供)
[php]
echo ~~4.9;
echo floor(4.9);
[/php]
用俩次非运算的速度基本上是floor的3倍, 不过有一点, 对于大数来说, 可能会发生溢出:
[php]
echo ~~99999999999999.99; //276447231
echo floor(99999999999999.99); //99999999999999
[/php]

8. do{}while(0)妙用(此条由Qianfeng提供)
我们知道do{}while(0)在c/c++中, 有很多妙用, 比如消除goto, 宏定义代码块.
所以, PHP中同理, 也可以用do{}while(0)来做一些巧妙的应用
[php]
do{
if(true) {
break;
}
if(true) {
break;
}
} while(false);
//好过
if(true) {
} else if(true) {
} else {
}
[/php]

9. 尽量少用@错误抑制符
如下代码:
[php]
@func();
[/php]
就相当于(参见深入理解PHP原理之错误抑制与内嵌HTML):
[php]
$report = error_reporting(0);
func();
error_reporting($report);
[/php]
另外错误抑制符号, 可能会造成一些问题, 参看(PHP错误抑制符(@)导致引用传参失败的Bug);
最后,错误抑制符在发生错误调试的时候也可能会带来麻烦.

10. 尽量避免使用递归(此条来自lazyboy)
递归性能堪忧, 而大部分的递归都是尾递归, 都是可以消除的.
[php]
function f($n) {
if ($n = 0) return 1;
return $n * f($n – 1);
}
//变为:
$result = 1;
for ($y = 1; $y < $n + 1; $y++ ) {
$result *= $y;
}
[/php]

11. 使用$_SERVER['REQUEST_TIME']代替time()
time()会引来一次函数调用, 而如果对时间的精确值要求不高, 可以使用$_SERVER['REQUEST_TIME']代替, 快很多.

12. 尽量避免使用正则(此条来自pangyontao)
正则耗时, 尽量避免, 而采用直接的字符串处理函数代替, 如:
[php]
if (preg_match("!^foo_!i", "FoO_")) { }
// 替换为:
if (!strncasecmp("foo_", "FoO_", 4)) { }
if (preg_match("![a8f9]!", "sometext")) { }
// 替换为:
if (strpbrk("a8f9", "sometext")) { }
if (preg_match("!string!i", "text")) {}
// 替换为:
if (stripos("text", "string") !== false) {}
[/php]
等等.

13. 用FALSE表示错误, 用NULL表示不存在.
对于操作类的函数, 失败返回FALSE, 表示”操作失败了”, 而对于查询类的函数, 如果找不到想要的值, 则应该返回NULL, 表示”找不到”.

作者: 石巍
原载: 风雪之隅->一些PHP Coding Tips
版权所有,转载时必须以超链接形式注明作者和原始出处及本声明。

本文链接: http://www.smartwei.com/javascript-url-redirect.html

分类: php知识 标签: ,

Firebug & Chrome Console 控制台使用指南

2011年3月24日 没有评论
Console API

当打开 firebug (也包括 Chrome 等浏览器的自带调试工具),window 下面会注册一个叫做 console 的对象,它提供多种方法向控制台输出信息,供开发人员调试使用。下面是这些方法的一个简单介绍,适时地运用它们,对于提高开发效率很有帮助。

console.log(object[, object, ...])
使用频率最高的一条语句:向控制台输出一条消息。支持 C 语言 printf 式的格式化输出。当然,也可以不使用格式化输出来达到同样的目的:

var animal='frog', count=10;
console.log("The %s jumped over %d tall buildings", animal, count);
console.log("The", animal, "jumped over", count, "tall buildings");

console.debug(object[, object, ...])
向控制台输出一条信息,它包括一个指向该行代码位置的超链接。

console.info(object[, object, ...])
向控制台输出一条信息,该信息包含一个表示“信息”的图标,和指向该行代码位置的超链接。

console.warn(object[, object, ...])
同 info。区别是图标与样式不同。

console.error(object[, object, ...])
同 info。区别是图标与样式不同。error 实际上和 throw new Error() 产生的效果相同,使用该语句时会向浏览器抛出一个 js 异常。

console.assert(expression[, object, ...])
断言,测试一条表达式是否为真,不为真时将抛出异常(断言失败)。

console.dir(object)
输出一个对象的全部属性(输出结果类似于 DOM 面板中的样式)。

console.dirxml(node)
输出一个 HTML 或者 XML 元素的结构树,点击结构树上面的节点进入到 HTML 面板。

console.trace()
输出 Javascript 执行时的堆栈追踪。

console.group(object[, object, ...])
输出消息的同时打开一个嵌套块,用以缩进输出的内容。调用 console.groupEnd() 用以结束这个块的输出。

console.groupCollapsed()
同 console.group(); 区别在于嵌套块默认是收起的。

console.time(name)
计时器,当调用 console.timeEnd(name);并传递相同的 name 为参数时,计时停止,并输出执行两条语句之间代码所消耗的时间(毫秒)。

console.profile([title])
与 profileEnd() 结合使用,用来做性能测试,与 console 面板上 profile 按钮的功能完全相同。

console.count([title])
输出该行代码被执行的次数,参数 title 将在输出时作为输出结果的前缀使用。

console.clear()
清空控制台

命令行

控制台的输出面板右边,是控制台的输入面板(Chrome 调试工具对应为下方),在这里除了可以运行常规的 javascript 代码,还内置了相当数量的命令行可以辅助我们的调试工作,下面是一些常用命令行的简单介绍。

$(id)
返回一个给定 id 的元素。

$$(selector)
返回给定的 css 选择器匹配到的一组元素。

$x(xpath)
返回给定的 XPath 表达式匹配到的一组元素。

$0
在 HTML 面板中选中的元素。

$1
上一次在 HTML 面板中选中的元素。

$n(index)
访问最近 5 个被选中过的元素,index 的范围: 0 – 4。

dir(object)
同 console.dir(object)。

dirxml(node)
同 console.dirxml(node)。

clear()
同 console.clear()。

inspect(object[, tabName])()
在合适的(或一个指定的) tab 中检视一个对象。

keys(object)
返回一个对象的所有属性的键。

values(object)
返回一个对象的所有属性的值。

debug(fn)
在函数第一行添加一个断点,使用 undebug(fn) 移除断点。

monitor(fn)
开启一个函数的调用日志,使用 unmonitor(fn) 关闭该功能。非常有用的一个命令,但是它似乎并没有很好地工作。

monitorEvents(object[, types])
开启一个元素的某个事件(或所有事件)被触发时的日志记录。用例如下:

monitorEvents($0,['click'])

上面的命令行被执行后,将开启当前在 HTML 面板中被选中元素的 click 事件监控,一旦这个元素的 click 事件被触发,事件对象将会在控制台输出。如果不指定第二个参数,将对所有事件进行记录。

profile([title])
同 console.profile([title])

《javascript精粹》读书笔记 – 数组

2011年1月23日 没有评论

1. 数组length属性的值是这个数组的最大整数属性名加上1.它不一定等于数组里属性的个数:
[js]
var myArray = [];
alert(myArray.length); // 0

myArray[1000000] = true;
alert(myArray.length); //1000001
[/js]

2. 在数组尾部添加一个新元素:
[js]
var numbers = ['zero', 'one', 'two'];
numbers[numbers.length] = ‘three’;
numbers.push(‘four’);
[/js]

3. 删除数组元素。
js中的数组实际上就是对象,所以delete运算符就可以用来从数组中移除元素:
[js]
var numbers = ['one', 'two', 'three', 'four'];
delete numbers[2]; // ['one', 'two', undefined, 'four']
[/js]
不幸的是,那样会在数组中遗留一个空洞。 通常可以使用splice方法来删除元素:
[js]
var numbers = ['one', 'two', 'three', 'four'];
numbers.splice(2, 1); //['one', 'two', 'four']
[/js]
这个对大型数组来说可能会效率不高。

4. 当属性名是小而连续的整数时,应该使用数组;否则使用对象。

5. 判断是否是数组:
[js]
var is_array = function(value){
return value &&
typeof value === ‘object’ &&
value.constructor === Array;
};
[/js]
不幸的是,它在识别从不同的窗口(window)或帧(frame)里构造的数组时会失败。完整的测试方法如下:
[js]
var is_array = function(value){
return value &&
typeof value === ‘object’ &&
typeof value.length === ‘number’ &&
typeof value.splice === ‘function’ &&
!(value.propertyIsEnumberable(‘length’));
};
[/js]

《javascript精粹》读书笔记 – 函数

2011年1月14日 没有评论

1. 当实际参数的个数与形式参数的个数不匹配时,不会导致错误。
如果实际参数值过多了,超出的参数值将被忽略;如果实际的参数值过少,缺失的值将被替换为undefined。

2. 在javascript中一共有四种调用模式: 方法调用模式、函数调用模式、构造器调用模式和apply调用模式。这些模式在如何初始化关键参数this上存在差异。
a.方法调用模式:
当一个函数被保存为对象的一个属性时,我们称它为一个方法。方法调用模式可以使用this去访问对象,所以它能够从对象中取值或修改对象。
b.函数调用模式:
当一个函数并非一个对象的属性时,它被当作一个函数来调用。当函数以此模式调用时,this被绑定到全局变量,这是语言设计上的一个错误。(正确的情况:当内部函数被调用时,this应该仍然被绑定到外部函数的this变量。)解决方法:如果该方法定义一个变量并给他赋值为this,那么内部函数就可以通过那个变量访问到this,按照约定,给那个变量命名为 that:
[js]
//给 myObject增加一个double方法
myObject.double = function()
{
var that = this; //解决方法

var helper = function()
{
that.value = add(that.value, that.value);
}

helper(); //以函数的形式调用helper。
}

//以方法的形式调用double
myObject.double();
[/js]
c.构造器调用模式:
在一个函数前面带上new来调用,那么将创建一个隐藏连接到该函数的prototype成员的新对象,同时this将会被绑定到那个新对象上。
[js]
//创建一个名为Quo的构造函数。它构造一个带有status属性的对象
var Quo = function(String)
{
this.status = String;
}

//给Quo的所有实例提供一个名为get_status的公共方法
Quo.prototype.get_status = function()
{
return this.status;
}

//构造一个Quo实例
var myQuo = new Quo("confused"); //构造器模式调用
document.writeln(myQuo.get_status());
[/js]
按照约定,构造器函数保存在以大写格式命名的变量里。
d.Apply调用模式:
apply方法接受两个参数,第一个是将被绑定给this的值,第二个就是参数数组。它让我们构建一个参数数组并用其去调用函数。
[js]
//构造一个Quo实例
var myQuo = new Quo("confused"); //构造器模式调用
document.writeln(myQuo.get_status());

//构建一个包含两个数字的数组,并将他们相加
add = function(a, b)
{
return a+b;
}

var anArray = [3, 4];
var sum = add.apply(null, anArray); //7

//构建一个包含status成员的对象
var statusObject = {
status: "A-OK"
};

//statusObject并没有继承自Quo.prototype,但我们可以再statusObject上调用
//get_status方法,尽管statusObject并没有一个名为get_status的方法。
var status = Quo.prototype.get_status.apply(statusObject);
[/js]

3. 参数:
当一个函数被调用时,会有一个默认的参数,就是 arguments “数组”。
[js]
//构造一个将很多值相加的函数

//注意该函数内部定义的变量sum不会与函数外部定义的sum产生冲突。
//该函数只能看到内部的那个变量。
var sum = function()
{
var i, sum=0;
for(i = 0; i < arguments.length; i+=1)
{
sum += arguments[i];
}
return sum;
};

document.writeln(sum(4, 8, 15, 16, 23, 42)); //108
[/js]
注:arguments并不是一个真正的数组。它知识一个“类似数组”的对象。arguments用友一个length属性,但它缺少所有的数组方法。

4. 返回:
一个函数总是会返回一个值。如果没有置顶返回值,则返回undefined。
如果函数以构造器方式被调用,且返回值不是一个对象,则返回this(该新对象)。

5.给类型增加方法:
[js]
Function.prototype.method = function(name, func)
{
this.prototype[name] = func;
return this;
}

//给Number添加一个integer方法,来提取数字钟的整数部分
//根据正负来判断是使用Math.ceil还是Math.floor
Number.method(‘integer’, function(){
return Math[this < 0 ? 'ceil' : 'floor'](this);
});

document.writeln((-10/3).integer()); //-3

//去掉字符串两端空白的方法
String.method(‘trim’, function()
{
return this.replace(/^\s+|\s+$/g, ”);
});
[/js]
基本类型的原型是公共结构,所以在类库混用时务必小心。一个保险的做法就是只在确定没有该方法时再添加:
[js]
//有条件的增加一个方法

Function.prototype.method = function(name, func)
{
if(!this.prototype[name])
{
this.prototype[name] = func;
return this;
}
};
[/js]

6.闭包
理解内部函数能访问外部函数的实际变量而无需复制
[js]
//构造一个函数,用错误的方式给一个数组中的借点设置事件处理程序
//当点击一个节点时,按照预想应该弹出一个对话框显示节点的序号
//但他总是会显示节点的数目

var add_the_handlers = function(nodes) {
var i;
for (i = 0; i < nodes.length; i += 1) {
nodes[i].onclick = function(e) {
alert(i);
}
}
}
[/js]
add_the_handlers函数的目的是给每个事件处理器一个唯一值(i)。它未能达到目的的原因是事件处理器函数绑定了变量i,而不是函数在构造时的变量i的值
正确的写法:
[js]
//点击一个节点,将会弹出一个对话框显示节点的序号
var add_the_handlers = function (nodes) {
var i;
for (i = 0; i < nodes.length; i +=1 ) {
nodes[i].onclick = function (i) {
return funtion (e) {
return alert(e);
} ;
}(i);
}
}
[/js]
现在,定义了一个函数并立即传递i进去执行, 而不是把一个函数赋值给onclick。那个函数将返回一个事件处理器函数。这个事件处理器函数绑定的是传递进去的i的值,而不只定义在add_the_handlers函数里的i的值。那个被返回的函数被复制给onclick。

7.javascript的单例模式
Javascript的单例就是用对象字面量表示法创建的对象,对象的属性值可以是数值或函数,并且属性值在该对象的生命周期中不会发生变化。他通常作为工具为程序其他部分提供功能支持

8.模块
模块模式的一般形式是:一个定义了私有变量和函数的函数;利用闭包创建可以访问私有变量和函数的特权函数,或者把他们保存到一个可访问的地方。
[js]
String.method(‘deentityify’, function (){
var entity = {
quot: ‘"’,
lt: ‘<’,
gt: ‘>’
}

return function () {
return this.replace(/&([^&;]+);/g,
function (a, b) {
var r = entity[b];
return typeof r === ‘string’ ? r : a;
});
};
}());
[/js]
模块模式利用了函数作用域和闭包来创建绑定对象与私有成员关联,摒弃了全局变量的使用,从而缓解这个JavaScript的最为糟糕的特性之一所带来的影响

《javascript精粹》读书笔记 – 对象

2011年1月9日 没有评论

《javascript精粹》中和对象相关的内容:

1. 当尝试检索对象的一个并不存在的成员元素的值,将返回一个undefined值。可以通过“||”运算符来填充默认值:
[js]
stooge["middle-name"] //undefined
var middle = stooge["middle-name"] || "tom";
[/js]

2. 当尝试检索一个undefined值将会导致TypeError异常。可以通过“&&”运算符来避免错误:
[js]
flight.equipment //undefined
flight.equipment.model //throw "TypeError"
flight.equipment && flight.equipment.model //undefined
[/js]

3. 对象通过引用来传递。他们永远不会被拷贝
[js]
var x = stooge;
x.nickname = ‘Curly’;
var nick = stooge.nickname;
//因为x和stooge是指向同一个对象的引用,所以nick的值为’Curly’

var a={}, b={}, c={};
//a, b和c每个都引用一个<strong>不同</strong>的空对象

a=b=c={}
//a,b和c都引用<strong>同一个</strong>空对象
[/js]

4. 原型连接
通过beget方法创建一个使用原对象作为其原型的新对象
[js]
if (typeof Object.beget !== ‘function’)
{
Object.beget = function (o)
{
var F = function () {};
F.prototype = o;
return new F();
}
}

var another_stooge = Object.beget(stooge);
[/js]
注:
a. 原型连接在更新时是不起作用的
当我们对某个对象作出改变时,不会触及到该对象的原型。
b. 原型连接只有在检索值的时候才被用到
如果尝试去获取对象的某个属性值,且该对象没有此属性名,那么从它的圆形对象中获取属性值。 (如果那个原型对象也没有该属性值,那么再从它的原型中寻找,依次类推,知道该过程左后的重点Object.prototype。如果想要的属性完全不存在于原型链中,那么结果就是undefined值。这个过程称为委托
c. 原型关系是一种动态关系。
如果我们添加一个新的属性到原型中,该属性会立即对所有基于该原形创建的对象可见。

5. 反射
在一些时候下,我们需要能够在对对象完全不了解的情况下进行处理,并且在处理之前发现他们的属性和方法,这个过程称作反射(reflection)。
在判断对象是否有某一属性时,可以使用”hasOwnProperty“方法,如果对象拥有独有的属性,它将返回true。
注:hasOwnProperty方法不会检查原型链。

6. 枚举
for in 语句可以用来遍历一个对象中的所有属性名。
属性名出现的顺序是不确定的,因此要对任何可能出现的顺序有所准备。如果你想要确保属性以特定的顺序出现,最好的办法就是完全避免使用for in语句,而是创建一个数组,在其中以正确的顺序包含属性名:
[js]
//使用for in语句:
var name;
for (name in another_stooge)
{
if(typeof another_stooge[name] !== ‘function’)
{
document.writeln(name + ‘: ‘ + another_stooge[name]);
}
}

//使用for语句
var i;
var properties = [
'first-name',
'middle-name',
'last-name',
'profession'
]
for (i=0; i<properties.length; i +=1)
{
document.writeln(properties[i] + ‘: ‘ +
another_stooge[properties[i]]);
}
[/js]

利用 PHP 5.3 的 lambdas 和 closures

2011年1月7日 1 条评论

了解如何使用 PHP 5.3 的 lambdas 和 closures。寻找您考虑使用它们的原因以及降低代码的复杂性的方法。最后,了解 closure 词法范围变量的行为。
详细内容

分类: php知识 标签:

2011年了

2011年1月1日 没有评论

2010年:
1.写了100篇文章
2.换了一份工作
3.渐渐习惯了在linux平台上开发
4.体重先减了10斤又弹了回去 – -!
5.看了了指定的小说

2010年憧憬:
1.健康的瘦到150-160
2.对javascript的使用可以达到前端工程师的水平
3.更多的关注一下php代码的性能,形成自己跟踪、分析bug的风格
4.灵活使用linux进行日常事务处理
5.提高自己的收入

分类: 未分类 标签:

array_merge, array_splice, array_slice使用时需要注意的地方

2010年12月20日 没有评论

今天在灌数据的时候,发生了一个十分奇怪的现象,看下代码:
[php]
$a = array
(
’1008/1009′ => 1,
’6065′ => 1,
’1002′ => 1,
‘K1024/K1021′ => 1,
);

array_slice($a, 3);
var_dump($a);
[/php]
期待的结果是:
[html]
array(3) {
["1008/1009"] => int(1)
["6065"] => int(1)
["1002"] => int(1)
}
[/html]

而实际上的输出结果会变成:

[html]
array(3) {
["1008/1009"] => int(1)
[0] => int(1)
[1] => int(1)
}
[/html]
可以看到数组$a中以数字最为key的项发生了变化,详细看了一下手册发现:
如果数组包含数字键名,array_splice将重置数组的键。 这一现象在array_merge中也会发生。

解决的办法有很多种,可以使用array_slice替换array_splice。array_slice( array $array , int $offset [, int $length [, bool $preserve_keys ]] ) 默认也会重置数组的键。自 PHP 5.0.2 起,可以通过将 preserve_keys 设为 TRUE 来改变此行为。

如果是在使用array_merge是出现这个问题,则可以直接使用”+”来代替

作者: 石巍
原载: 10V的博客
版权所有,转载时必须以超链接形式注明作者和原始出处及本声明。

本文链接: http://www.smartwei.com/php-array-attention.html

分类: php知识 标签:

Phing – PHP代码构建系统

2010年12月19日 没有评论

什么是Phing?
Phing是一个基于Apache Ant的项目代码构建系统.你可以用她做传统的构建系统能做的任何事情,比如GNU make,并且Phing使用简单的XML构建文件和可扩展的”任务”使之成为易于使用和极具可扩展性的框架.
phing全名是phing is not GUN make, 我们可以使用Phing来实现php应用程序自动化部署。

Phing怎样工作
Phing使用包含一组项目构建描述的XML构建文件.构建文件由一些运行实际的命令的目标组成(比如复制文件,删除目录,执行数据库查询,等等).因此使用Phing,第一步要编写构建文件,然后运行Phing,在构建文件中定义的要执行的目标.
默认情况下,Phing将会查找一个叫build.xml的文件.(除非构建文件的名称不是build.xml,否则不必为Phing指定构建文件的名称) 并且,如果没有指定任何目标那么Phing将执行在
标签中设置的默认目标(default属性所指定的).

phing的安装

[php]
sudo pear channel-discover pear.phing.info
sudo pear install phing/phing
sudo pear install channel://pear.php.net/VersionControl_SVN-0.3.3
[/php]

phing的使用
编写一个简单的构建文件:

[html]
<?xml version="1.0"?>

<project name="FooBar" default="dist" basedir=".">

<!—创建文件夹–>

<target name="prepare">

<echo msg="Preparing build…" />

<mkdir dir="./build" />

</target>

<!—复制文件–>

<target name="build" depends="prepare">

<echo>Building…</echo>

<copy file="./src/File.php" to="./build/File.php"/>

<copy file="./src/File2.php" to="./build/File2.php"/>

</target>

<!—打包–>

<target name="dist" depends="build">

<echo message="Creating archive…" />

<tar outfile="furbee.tar.gz" basedir="./build"/>

</target>

<!—删除,清理–>

<target name="clean">

<echo msg="Cleaning up…"/>

<delete file="./build"/>

</target>

</project>
[/html]

Phing的元素
project 元素: 文件序言之后紧跟着的第一个元素的是 , 此元素是一个包含其他元素的容器,并且有以下属性:

属性 含义
name 项目的名称
basedir 项目的根目录,如果未指定将使用当前目录
default 在调用构建文件的时候,如果没有指定要执行的目标, 将执行在此定义的项目默认目标

target 元素: 一个目标可依赖其他的目标.你可能有一个在构建树中安装文件的目标,例如,创建一个tar.tgz分发包的目标. Target元素的属性:

属性 含义
name target的名称
depends 此target依赖的前置target;逗号分隔列表
if 为了使此目标得以执行而必须设置的属性的名称
unless 为了使此目标得以执行而禁止设置的属性的名称

任务元素: 一个任务是一段可执行的PHP代码段.此代码段实现了特定的行为(例如,复制文件).因此你必须在构建文件中定义,才能是Phing真正的调用它. 任务可以被分配一个id属性:
[html]
<taskname id=”taskID” …/>
[/html]

property 元素:属性是在构建文件使用的基本的变量,可以在构建文件中通过 PropertyTask任务设置或在Phing外部通过命令行传递.通过命令行传递的属性总是会覆盖在构建文件中设置的属性,也就是说命令行是最后传递给Phing的,自然会覆盖先前在构建文件中设置的属性.
属性有一个名称和一个唯一的值.属性可以作为任务属性的值.这是通过在”${”和”}”包含属性名称来设置的.例如:
[html]
<propery name=”javasourcedir” value=”./src/java”/>

<javac srcdir=”${javasourcedir}”/>
[/html]
这里在运行时${javasourcedir}将被展开为./src/java 。

更复杂的构建文件:
[html]
<?xml version="1.0"?>
<project name="lap" basedir="." default="help">

<property name="builddir" value="./build"/>
<property name="modulesDir" value="/usr/local/php5/lib/Modules"/>
<property name="domain" value="cardii.net"/>

<target name="prepare">
<echo msg="Preparing build…" />
<mkdir dir="${builddir}/public" />
<mkdir dir="${builddir}/lib" />
<mkdir dir="${builddir}/Modules" />
<mkdir dir="${builddir}/Websites" />
</target>

<target name="get">
<echo>Checkout lap code …</echo>
<svncheckout svnpath="/usr/bin/svn" repositoryurl="http://${domain}/svn/Dh" todir="${builddir}"/>

<echo>Checkout builddirs root template …</echo>
<svncheckout svnpath="/usr/bin/svn" repositoryurl="http://${domain}/svn/Websites" todir="${builddir}/Websites"/>
<echo>Changing file permissions…</echo>
<chmod mode="0777">
<fileset dir="${builddir}/Websites" />
</chmod>

<echo> Copying dir fckeditor and phpmyadmin …</echo>
<copy todir="${builddir}/Modules">
<fileset dir="${modulesDir}">
<include name="fckeditor/**"/>
<include name="phpmyadmin/**"/>
</fileset>
</copy>
</target>

<target name="backup-db" description="Backup the database before upgrade.">
<if>
<not>
<isset property="db.password" />
</not>
<then>
<input propertyname="db.password" promptChar=":">Enter password for user ${db.user} for database ${db.name}</input>
</then>
</if>
<exec command="${extern.mysqldump} –quick — password=${db.password} –user=${db.user} ${db.name} > ${db.name}.${DSTAMP}${TSTAMP}.sql" dir="${db.backup.dir}" escape="false" />

<zip destfile="${db.backup.dir}/${db.name}.${DSTAMP}${TSTAMP}.sql.zip">
<fileset dir="${db.backup.dir}">
<include name="${db.name}.${DSTAMP}${TSTAMP}.sql" />
</fileset>
</zip>
<delete file="${db.backup.dir}/${db.name}.${DSTAMP}${TSTAMP}.sql" />
</target>

<target name="help">
<echo>
Welcome to use Lap build script!
——————————–
You may use the following command format to build a target:

phing &lt;target name&gt;

where &lt;target name&gt; can be one of the following:

phing prepare
phing get
phing backup-db

-Dbuilddir="./$websitename" : $websitename required eg.s3shop.com.
-DmodulesDir="/usr/local/php/lib/Modules" : Modules path, not required
-Ddomain="cardii.com" : svn address.default: cardii.net
-f bulid.xml : not required
</echo>
</target>

</project>

[/html]

作者: 石巍
参考文章: PHP工具介绍之二–项目自动化部署工具phingPhing用户指南
链接: http://www.smartwei.com/js-add-event.html

分类: php知识 标签:

js DOM 事件绑定

2010年11月11日 没有评论

Js绑定DOM事件
[js]
function addEvent( obj, type, fn ) {
if( obj.attachEvent ) {
obj[ 'e' + type + fn ] = fn;
obj[ type + fn ] = function() {
ojb[ 'e' + type + fn ]( window.event );
}
obj.attachEvent( ‘on’ + type, obj[ type + fn ]);
}
else {
obj.addEventListener( type, fn, false );
}
}

function removeEvent( ojb, type, fn ) {
if( obj.detachEvent ) {
obj.detachEvent( ‘on’ + type + obj[ type + fn ] );
obj[ type + fn ] = null;
}
else {
ojb.removeEventListener( type, fn, false );
}
}
[/js]

JS绑定onLoad事件
[js]
function addLoadEvent( func ) {
var oldonload = window.onload;
if( typeof window.onload != ‘function’ ) {
window.onload = func;
}
else {
window.onload = function() {
oldonload();
func();
}
}
}
[/js]
作者: 石巍
原载: 10V的博客
链接: http://www.smartwei.com/js-add-event.html
版权所有,转载时必须以超链接形式注明作者和原始出处及本声明。

分类: javascript 标签: