存档

文章标签 ‘php’

一些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知识 标签: ,

工作收获碎碎念20101021 – 石巍的博客10V

2010年10月21日 没有评论

1. realpath可以获得绝对路径
2. 全局文件中使用静态变量可以减少加载文件的时间 (静态数组中存放需要加载的文件,如果已经加载则直接返回true,未加载则加载并在静态数组中添加该文件)
3. redirct可以通过header(“refresh: {$time};url={$url}”); 来设置延时跳转到对应的url
4. $objects[$class] = & new $class(); 这里的&可以是实例化的对象以引用的方式传递,不需要复制(单例模式)
5. trim($str, $mark)可以过滤掉$str头尾出现的$mark字符串,默认mark为\s
6. 可以通过$_SERVER['HTTP_USER_AGENT']来判断是否是浏览器过来的请求
7. 在获取当前时间时,先执行date_default_timezone_set(“PRC”);可以获取更准确的中国时间
8. 在截字时,可以通过mb_internal_encoding(“UTF-8″);来设置截取字符串的编码,并通过mb_strlen和mb_substr来正确截字
9. $this->{$this->act}(); 这样可以省去很多代码
10. YSLOW研究:
a. minify js和css;合并所有js到一个js;合并所有css到一个css;将css放在头部;将js放在尾部。
b. 当网站要分布式的时候,使用CDN(适合大中型网站,小网站不用考虑..)
c. 给静态内容增加一个长久的过期时间
d. 使用gzip压缩内容
e. 减少DNS查询:尽量让页面上面的元素(图片,css等静态内容)不要使用不同域名的。否则会解析多个域名导致DNS多次查询影响速度
f. 设置Etag (Entity tags)
g. 减少dom数量

Smarty常用变量操作符

2010年6月17日 没有评论

capitalize[首字母大写]
count_characters[计算字符数]
cat[连接字符串]
count_paragraphs[计算段落数]
count_sentences[计算句数]
count_words[计算词数]
date_format[时间格式]
default[默认]
escape[转码] html,hemlall,url
indent[缩进]
lower[小写]
replace[替换]
regex_replace[正则替换]
spacify[插空]
string_format[字符串格式化]数字 %.2f
strip[去除(多余空格)]
strip_tags[去除HTML标签]
truncate[截取]
upper[大写]
wordwrap[行宽约束]

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

本文链接: http://www.smartwei.com/smarty-usual-function.html

分类: php知识 标签:

浅谈PHP中的Session机制

2010年5月11日 2 条评论

做web开发,必然会涉及到Session,这是由于http协议本身是无状态的(每次响应都是独立的,彼此间没有联系),所以如果需要在页面跳转间保持某个用户的身份,就要在每次连接时告诉服务器端你的唯一标示号,即Session ID。这样,服务器端便可通过Session ID得到所需的数据。

在PHP中,Session是通过$_SESSION这个全局变量来set/get的,不过在使用之前要先初始化。初始化是通过 session_start函数(如果php.ini中将session.auto_start设为1,则会自动初始化),之后PHP会为request 自动生成一个唯一随机数作为Session ID,生成算法默认提供了MD5 (128 bits) 和SHA-1 (160 bits),由php.ini中session.hash_function设定。其实也可以自定义,比如在随机数基础上将来访者的IP地址也加入到算法中,像CodeIgniter1.7.2中代码:

阅读全文…

分类: php知识 标签:

php面向对象编程 – 观察者模式

2010年4月27日 没有评论

observer
这篇文章介绍一下设计模式中的观察者模式。 观察者模式应用到php面向对象编程中,可以避免组件之间紧密耦合。另外的关于如何避免组件之间机密耦合的方法,可以参考php面向对象编程 – 使用接口实现松散耦合这篇文章。

观察者模式非常简单:一个对象通过添加一个方法(该方法允许另一个对象,即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。
阅读全文…

php面向对象编程 – 使用接口实现松散耦合

2010年4月26日 没有评论

先来看一个紧密耦合的例子:
[php]
<?php

require_once "./AddressFormatters.php";

class Address
{
private $addressLine1;
private $addressLine2;
private $city;
private $state; // or province…
private $postalCode;
private $country;

public function setAddressLine1($line1)
{
$this->addressLine1 = $line1;
}

/* accessors, etc… */

public function getCountry()
{
return $this->country;
}

public function format($type)
{
if ($type == "inline") {
$formatter = new InlineAddressFormatter();
} else if ($type == "multiline") {
$formatter = new MultilineAddressFormatter();
} else {
$formatter = new NullAddressFormatter();
}
return $formatter->format($this->getAddressLine1(),
$this->getAddressLine2(),
$this->getCity(), $this->getState(), $this->getPostalCode(),
$this->getCountry());
}
}

$addr = new Address();
$addr->setAddressLine1("123 Any St.");
$addr->setAddressLine2("Ste 200");
$addr->setCity("Anytown");
$addr->setState("AY");
$addr->setPostalCode("55555-0000");
$addr->setCountry("US");

echo($addr->format("multiline"));
echo("\n");

echo($addr->format("inline"));
echo("\n");

?>
[/php]
在 Address 对象上调用 format() 方法的代码可能看上去很棒 — 这段代码所做的是使用 Address 类,调用 format() 并完成。相反,Address 类就没那么幸运。它需要了解用于正确格式化的各种格式化方法,这可能使 Address 对象无法被其他人很好地重用,尤其是在其他人没有兴趣在 format() 方法中使用格式化方法类的情况下。虽然使用 Address 的代码没有许多依赖关系,但是 Address 类却有大量代码,而它可能只是一个简单的数据对象。

在构建优秀的 OO 设计时,必须考虑称为关注点分离(Separation of Concerns,SoC)的概念。SoC 指尝试通过真正关注的内容分离对象,从而降低耦合度。在最初的 Address 类中,它必须关注如何进行格式化。这可能不是优秀的设计。然而,Address 类应当考虑 Address 的各部分,而某种格式化方法应当关注如何正确格式化地址。
看一下如何通过使用接口来实现松散耦合:
[php]
<?php

interface AddressFormatter
{
public function format($addressLine1, $addressLine2, $city, $state,
$postalCode, $country);
}

class MultiLineAddressFormatter implements AddressFormatter
{
public function format($addressLine1, $addressLine2, $city, $state,
$postalCode, $country)
{
return sprintf("%s\n%s\n%s, %s %s\n%s",
$addressLine1, $addressLine2, $city, $state, $postalCode, $country);
}
}

class InlineAddressFormatter implements AddressFormatter
{
public function format($addressLine1, $addressLine2, $city, $state,
$postalCode, $country)
{
return sprintf("%s %s, %s, %s %s %s",
$addressLine1, $addressLine2, $city, $state, $postalCode, $country);
}
}

class AddressFormatUtils
{
public static function formatAddress($type, $address)
{
$formatter = AddressFormatUtils::createAddressFormatter($type);

return $formatter->format($address->getAddressLine1(),
$address->getAddressLine2(),
$address->getCity(), $address->getState(),
$address->getPostalCode(),
$address->getCountry());
}

private static function createAddressFormatter($type)
{
if ($type == "inline") {
$formatter = new InlineAddressFormatter();
} else if ($type == "multiline") {
$formatter = new MultilineAddressFormatter();
} else {
$formatter = new NullAddressFormatter();
}
return $formatter;
}
}

$addr = new Address();
$addr->setAddressLine1("123 Any St.");
$addr->setAddressLine2("Ste 200");
$addr->setCity("Anytown");
$addr->setState("AY");
$addr->setPostalCode("55555-0000");
$addr->setCountry("US");

echo(AddressFormatUtils::formatAddress("multiline", $addr));
echo("\n");

echo(AddressFormatUtils::formatAddress("inline", $addr));
echo("\n");
?>

[/php]

在上面的代码中,省略了address的部分代码。关键部分展示了:格式化地址的代码被移到接口、实现类和工厂中 — 养成 “使用接口” 的习惯。现在,AddressFormatUtils 类负责创建格式化方法并格式化 Address。任何其他对象现在都可以使用 Address 而不必担心要求获得格式化方法的定义。

当然,缺点是只要使用模式,通常就意味着工件(类、文件)的数量会增加。但是,通过减少每个类中的维护可以弥补这个缺点,甚至在获得正确的可重用性时反而可以减少工件量。

如果你想对php面向对象编程中接口的使用方法进一步了解的话,可以参考一下这篇文章:php接口学习 —— php面向对象编程

作者: 石巍
原载: 在 PHP 中养成 7 个面向对象的好习惯
版权所有,转载时必须以超链接形式注明作者和原始出处及本声明。

本文链接: http://www.smartwei.com/php-separation-of-concerns.html

获取脚本执行时间的php类 – 含有暂停功能

2010年3月9日 没有评论

php-class-time-tracking
上一篇文章,给大家介绍了一个获取脚本执行时间的php类, 今天再给大家介绍一个。今天的这个获取脚本执行时间的php类的特别之处是它提供了“暂停|开启”功能,可以让我们很方便的跳过某些代码的执行时间。

举个例子,当我们只想知道页面中SQL的执行时间是多长,我们就可以在每次进行SQL查询之前,开始计时,查询之后暂停计时,然后开始处理数据,下一次进行SQL查询时再开始计时…这样最终的执行时间,就是我们想要的SQL执行时间了。

下面看一下代码
阅读全文…

获取脚本执行时间的php类

2010年2月28日 1 条评论

Script Time Tracking
在平时的Php开发工程中,我经常会检测一下脚本的执行时间,如果发现脚本的执行时间比预想的长很多,那么肯定是这段脚本编写有问题,需要进行代码优化。下面给大家介绍一个获取脚本执行时间的php类
阅读全文…

php服务器端变量$_SERVER详解

2010年2月22日 没有评论

今天看到了一个帖子,是关于php服务器端变量$_SERVER的详解,觉得写的很不错,转载了和大家分享一下。帖子的原始出处是:珍爱生命,远离螃蟹

服务器变量 $_SERVER 详解:

1、$_SESSION['PHP_SELF'] — 获取当前正在执行脚本的文件名

2、$_SERVER['SERVER_PROTOCOL'] — 请求页面时通信协议的名称和版本。例如,“HTTP/1.0”。

3、$_SERVER['REQUEST_TIME'] — 请求开始时的时间戳。从 PHP 5.1.0 起有效。和time函数效果一样。

4、$_SERVER['argv'] — 传递给该脚本的参数。我试了下,get方法可以得到$_SERVER['argv'][0];post方法无法给他赋值。

5、$_SERVER['SERVER_NAME'] — 返回当前主机名。
阅读全文…

php面向对象编程-封装字符串处理函数

2009年12月28日 没有评论

众所周知,php5较以前版本更好的支持了面向对象编程。今天给大家介绍的php类是一个字符串处理类,它封装了字符串处理的常用函数,对于学习php面向对象编程的朋友们,可以从这个类的代码中学到一些封装的技巧和要考虑的东西。废话不多说了,来看看这个类:
阅读全文…