手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表分类:PHP

切勿过早优化

放在PHP栏目是我仔细想过的,虽然文章内容里并未提及到PHP
开发WEB,很多人在一开始就考虑了优化优化再优化,但是,如果按照你这样的优化下去,当你发现瓶劲的时候你怎么办?你已经无法优化了。。
因此,为自己的代码预留一点优化空间,先赶着把代码上线,然后再边运行边优化。一来也保证了上线的时间,二来也可以在运行时注意到哪些地方是需要重点优化的。

以下内容来自守望轩(博客园)的文章:原文http://www.cnblogs.com/xjb/archive/2009/04/13/no-premature-optimization.html

Donald Knuth说“过早优化是万恶之源”(premature optimization is the root of all evil)。这话也许有些夸张,但“过早优化”的危害我觉得不能忽视。同时,我觉得“过早优化”的概念不专属编写程序,生活中的示例也比比皆是。不信,你看看下面这些情形你是否遇到过:

http://www.watch-life.net/life-thinking/no-premature-optimization.html

1、当你开始学一门程序语言的时候(比如c#),你想如果可以精通开发工具(比如Visual Studio)一定如虎添翼,于是一开始你就花很多时间去研究开发工具,而忘记自己学习的重点是语言本身,而非工具。或者,一开始,你花不少的时间去选择哪门程序语言,比较各种语言的优劣,在五花八门的语言前面犹豫不决,这个想学,那个也不想放弃,结果都是学个半路子。

2、当你学习一门外语比如英语的时候,一开始,你花了很多的时间去下载有关英语资料,花了很多的时间去找英语书籍,以为有了这些资料和书籍就可以学好英文,而不是一开始就踏踏实实的从单词、语法开始,结果后来资料下载了一大堆,书籍买了不少,却没有坚持下去。

3、你想搞体育锻炼,比如打羽毛球,于是一开始你花大量时间去买球衣、球鞋、球拍等装备,可没连几天,你发现自己开始三天打鱼了,最后,那些装备都起了灰,也没锻炼几次。

4、你想做时间管理(Getting Things Done),于是你研究各种时间管理的资料,上各种时间管理技巧的网站,比如lifehack、 digg 、gtdlife,下载对最流行的GTD的管理软件,以节省时间的名义浪费时间,很浮躁,不能做到实实在在把每天的计划都落实,拖拖拉拉。

5、你有没有这样的体验,一本书你总是对开头的部分看的最仔细,后面的章节没坚持看下去,下次又重复这种循环。当你计划做一件事的时候,总是规划的 非常完美,几乎考虑每个细节,但却没有认认真真、一步一步执行,或者过早完美计划,反而让你缩手缩脚,犹豫不前,瞻前顾后,顾此失彼,最后虎头蛇尾。

6、比如,如果我有了钱,我就如何如何享受快乐,比如,如果我将来有了很多的时间,我就会花更多的时间陪家人或锻炼…

这样类似的例子还可以举很多。

过早优化对大的问题在于:过早关注不重要的部分,而忽略行动和目标本身。以静态的思维来优化,殊不知,事务发展总是动态的,“优化”是需要长期的实 践积累才可以获得。出发点是好的,但往往好心办坏事,折腾大量的时间,做了很多不该做的,而该做的、重要的反而没做。强化外部条件、工具等外在,而忽略内 在因素和行动本身,或者,过多期望将来,而忽略当下眼前。

活在当下,实实在在做好手头的事,是避免“过早优化”最好的方法之一

Tags: 优化

一个很旧的PHP分词程序

这是一个比较老的分词程序,原文中的一些链接现在不是地址不正确就是打不开了。由此可以证明它是多老了。
再加上PHP直接进行分词的性能本来就不咋地,因此,建议仅仅用在很小的地方,比如自动添加TAG之类的。

原文如下:http://blog.sina.com.cn/s/blog_5677bc54010000i5.html

用PHP去做中文分词并不是一个太明智的举动, :p

下面是我根据网上找的一个字典档, 简易实现的一个分词程序.

(注: 字典档是gdbm格式, key是词 value是词频, 约4万个常用词)
代码请参见http://www.shi8.com/out/support/art_316.txt

PHP代码
  1. <?php  
  2. //中文分词系统简易实现办法  
  3. //切句单位:凡是ascii值<128的字符  
  4. //常见双字节符号:《》,。、?“”;:!¥…… %$#@^&*()[]{}|\/"'  
  5. //可以考虑加入超常见中文字: 的 和 是 不 了 啊 (不过有特殊字比如 "打的" "郑和" .. :p)  
  6.   
  7. //计算时间  
  8. function getmicrotime(){  
  9.     list($usec$sec) = explode(" ",microtime());  
  10.     return ((float)$usec + (float)$sec);  
  11. }  
  12. $time_start = getmicrotime();  
  13.   
  14.   
  15. //词典类  
  16. class ch_dictionary {  
  17.     var $_id;  
  18.   
  19.     function ch_dictionary($fname = "") {  
  20.         if ($fname != "") {  
  21.             $this->load($fname);  
  22.         }  
  23.     }  
  24.   
  25.     // 根据文件名载入字典 (gdbm数据档案)  
  26.     function load($fname) {  
  27.         $this->_id = dba_popen($fname"r""gdbm");  
  28.         if (!$this->_id) {  
  29.             echo "failed to open the dictionary.($fname)<br>\n";  
  30.             exit;  
  31.         }  
  32.     }  
  33.   
  34.     // 根据词语返回频率, 不存在返回-1  
  35.     function find($word) {  
  36.         $freq = dba_fetch($word$this->_id);  
  37.         if (is_bool($freq)) $freq = -1;  
  38.         return $freq;  
  39.     }  
  40. }  
  41.   
  42. // 分词类: (逆向)  
  43. // 先将输入的字串正向切成句子, 然后一句一句的分词, 返回由词组成的数组.  
  44. class ch_word_split {  
  45.     var $_mb_mark_list;    // 常见切分句子的全角标点  
  46.     var $_word_maxlen;    // 单个词最大可能长度(汉字字数)  
  47.     var $_dic;        // 词典...  
  48.     var $_ignore_mark;    // true or false  
  49.      
  50.     function ch_word_split () {  
  51.         $this->_mb_mark_list = array(","," ","。","!","?",":","……","、","“","”","《","》","(",")");  
  52.         $this->_word_maxlen  = 12;    // 12个汉字  
  53.         $this->_dic = NULL;  
  54.         $this->_ignore_mark = true;  
  55.     }  
  56.   
  57.     // 设定字典  
  58.     function set_dic($fname) {  
  59.         $this->_dic = new ch_dictionary($fname);  
  60.     }  
  61.   
  62.     function set_ignore_mark($set) {  
  63.         if (is_bool($set)) $this->_ignore_mark = $set;  
  64.     }  
  65.   
  66.     // 将字串切成句子再加以切分成词  
  67.     function string_split($str$func = "") {         
  68.         $ret = array();  
  69.          
  70.         if ($func == "" || !function_exists($func)) $func = "";         
  71.          
  72.         $len = strlen($str);  
  73.         $qtr = "";  
  74.   
  75.         for ($i = 0; $i < $len$i++) {  
  76.             $char = $str[$i];  
  77.   
  78.             if (ord($char) < 0xa1) {  
  79.                 // 读取到一个半角字符  
  80.                 if (!emptyempty($qtr)) {  
  81.                     $tmp = $this->_sen_split($qtr);  
  82.                     $qtr = "";  
  83.   
  84.                     if ($func != "") call_user_func($func$tmp);                     
  85.                     else $ret = array_merge($ret$tmp);                     
  86.                 }  
  87.   
  88.                 // 如果是单词或数字. 根据 char 将数据读取到 >= 0xa1为止  
  89.                 if ($this->_is_alnum($char)) {  
  90.                     do {  
  91.                         if (($i+1) >= $lenbreak;  
  92.                         $char2 = substr($str$i + 1, 1);  
  93.                         if (!$this->_is_alnum($char2)) break;  
  94.   
  95.                         $char .= $char2;  
  96.                         $i++;  
  97.                     } while (1);  
  98.   
  99.                     if ($func != "") call_user_func($funcarray($char));  
  100.                     else $ret[] = $char;                     
  101.                 }  
  102.                 elseif ($char == ' ' || $char == "\t") {  
  103.                     // nothing.  
  104.                     continue;  
  105.                 }  
  106.                 elseif (!$this->_ignore_mark) {  
  107.                     if ($func != "") call_user_func($funcarray($char));  
  108.                     else $ret[] = $char;                     
  109.                 }  
  110.             }  
  111.             else {  
  112.                 // 双字节字符.  
  113.                 $i++;  
  114.                 $char .= $str[$i];  
  115.                  
  116.                 if (in_array($char$this->_mb_mark_list)) {  
  117.                     if (!emptyempty($qtr)) {  
  118.                         $tmp = $this->_sen_split($qtr);  
  119.                         $qtr = "";  
  120.   
  121.                         if ($func != "") call_user_func($func$tmp);  
  122.                         else $ret = array_merge($ret$tmp);  
  123.                     }  
  124.   
  125.                     if (!$this->_ignore_mark) {  
  126.                         if ($func != "") call_user_func($funcarray($char));  
  127.                         else $ret[] = $char;  
  128.                     }  
  129.                 }  
  130.                 else {  
  131.                     $qtr .= $char;  
  132.                 }  
  133.             }  
  134.         }  
  135.          
  136.         if (strlen($qtr) > 0) {  
  137.             $tmp = $this->_sen_split($qtr);  
  138.   
  139.             if ($func != "") call_user_func($func$tmp);             
  140.             else $ret = array_merge($ret$tmp);             
  141.         }  
  142.   
  143.         // return value  
  144.         if ($func == "") {  
  145.             return $ret;  
  146.         }  
  147.         else {  
  148.             return true;  
  149.         }  
  150.     }  
  151.   
  152.     // 将句子切成词, 逆向  
  153.     function _sen_split($sen) {  
  154.         $len = strlen($sen) / 2;  
  155.         $ret = array();  
  156.   
  157.         for ($i = $len - 1; $i >= 0; $i--) {  
  158.             // 如: 这是一个分词程序  
  159.              
  160.             // 先取得最后一个字  
  161.             $w = substr($sen$i * 2, 2);  
  162.   
  163.             // 最终的词长  
  164.             $wlen = 1;  
  165.              
  166.             // 开始逆向匹配到最大长度.  
  167.             $lf = 0; // last freq  
  168.             for ($j = 1; $j <= $this->_word_maxlen; $j++) {  
  169.                 $o = $i - $j;  
  170.                 if ($o < 0) break;  
  171.                 $w2 = substr($sen$o * 2, ($j + 1) * 2);  
  172.                  
  173.                 $tmp_f = $this->_dic->find($w2);  
  174.                 //echo "{$i}.{$j}: $w2 (f: $tmp_f)\n";  
  175.                 if ($tmp_f > $lf) {  
  176.                     $lf = $tmp_f;  
  177.                     $wlen = $j + 1;  
  178.                     $w = $w2;  
  179.                 }  
  180.             }  
  181.             // 根据 $wlen 将 $i 偏移了  
  182.             $i = $i - $wlen + 1;  
  183.             array_push($ret$w);  
  184.         }  
  185.   
  186.         $ret = array_reverse($ret);  
  187.         return $ret;  
  188.     }  
  189.   
  190.     // 判断字符是不是 字母数字_- [0-9a-z_-]  
  191.     function _is_alnum($char) {  
  192.         $ord = ord($char);  
  193.         if ($ord == 45 || $ord == 95 || ($ord >= 48 && $ord <= 57))  
  194.             return true;  
  195.         if (($ord >= 97 && $ord <= 122) || ($ord >= 65 && $ord <= 90))  
  196.             return true;  
  197.         return false;  
  198.     }  
  199. }  
  200.   
  201.   
  202. // 分词后的回调函数  
  203. function call_back($ar) {     
  204.     foreach ($ar as $tmp) {  
  205.         echo $tmp . " ";  
  206.         //flush();  
  207.     }  
  208. }  
  209.   
  210. // 实例(如果没有输入就从 sample.txt中读取):  
  211. $wp = new ch_word_split();  
  212. $wp->set_dic("dic.db");  
  213.   
  214. if (!isset($_REQUEST['testdat']) || emptyempty($_REQUEST['testdat'])) {  
  215.     $data = file_get_contents("sample.txt");  
  216. }  
  217. else {  
  218.     $data = & $_REQUEST['testdat'];  
  219. }  
  220.   
  221. // output  
  222. echo "<h3>简易分词演示</h3>\n";  
  223. echo "<hr>\n";  
  224. echo "分词结果(" . strlen($data) . " chars): <br>\n<textarea cols=100 rows=10>\n";  
  225.   
  226. // 设定是否忽略不返回分词符号(标点,常用字)  
  227. $wp->set_ignore_mark(false);  
  228.   
  229. // 执行切分, 如果没有设置 callback 函数, 则返回由词组成的array  
  230. $wp->string_split($data"call_back");  
  231.   
  232. $time_end = getmicrotime();  
  233. $time = $time_end - $time_start;  
  234.   
  235. echo "</textarea><br>\n本次分词耗时: $time seconds <br>\n";  
  236. ?>  
  237. <hr>  
  238. <form method=post>  
  239. 您也可以在下面文本框中输入文字,提交后试验分词效果:<br>  
  240. <textarea name=testdat cols=100 rows=10></textarea><br>  
  241. <input type=submit>  
  242. </form>  
  243. <hr>  

文章引用自:http://www.im286.net/viewthread.php?tid=1157015

Tags: 分词, gbm

[转]PHP删除cookie的一个小秘密

首先我们看一下php手册中关于删除cookie的说明

------以下引用php手册内容--------------

bool setcookie ( string name [, string value [, int expire [, string path [, string domain [, bool secure]]]]] )



要删除 cookie 需要确保它的失效期是在过去,才能触发浏览器的删除机制。
下面的例子说明了如何删除刚才设置的 cookie: 例子 2. setcookie() 删除
例子

// 将过期时间设为一小时前

setcookie("TestCookie", "", time() - 3600);
setcookie("TestCookie", "", time() - 3600, "/~rasmus/", ".utoronto.ca", 1);

----------------引用结束--------------------------

删除一个cookie的方法就是把这个cookie的有效期设置为当前时间以前,这
也是几乎所有php程序员都会这么做。

  后来一个初接触php的朋友告诉我,他在程序中本想把一个cookie的值设置为
空,结果导致这个cookie直接被删除。我当时的第一反应是不相信,于是测试
了一下

setcookie("testcookie", '');
print_r($_COOKIE);

结果果然是整个$_COOKIE数组都是空的,而非仅仅$_COOKIE['testcookie']为
空.于是用winsock抓包,观察返回的http头,发现http头竟然是

Set-Cookie: testcookie=deleted; expires=Mon, 18-Jun-2007 02:42:33 GMT



这说明setcookie("testcookie", '');的的确确是将testcookie这个cookie直
接删除.而关于这种情况在php手册中完全没有说明.

最后阅读php源码,终于发现真相(这就是开源的好处了,有什么不清楚的内幕
直接查源码)

以下代码可以在php5.20的linux源码包中ext/standard/head.c第99行附近找到.

C++代码
  1. if (value && value_len == 0) {  
  2.     /* 
  3.      * MSIE doesn't delete a cookie when you set it to a null value 
  4.      * so in order to force cookies to be deleted, even on MSIE, we 
  5.      * pick an expiry date 1 year and 1 second in the past 
  6.      */  
  7.     time_t t = time(NULL) - 31536001;  
  8.     dt = php_format_date("D, d-M-Y H:i:s T"sizeof("D, d-M-Y H:i:s T")-1, t, 0 TSRMLS_CC);  
  9.     sprintf(cookie, "Set-Cookie: %s=deleted; expires=%s", name, dt);  
  10.     efree(dt);  
  11. else {  
  12.     sprintf(cookie, "Set-Cookie: %s=%s", name, value ? encoded_value : "");  
  13.     if (expires > 0) {  
  14.         strcat(cookie, "; expires=");  
  15.     dt = php_format_date("D, d-M-Y H:i:s T"sizeof("D, d-M-Y H:i:s T")-1, expires, 0 TSRMLS_CC);  
  16.         strcat(cookie, dt);  
  17.         efree(dt);  
  18.     }  
  19. }  



源码中清清楚楚的显示,if (value && value_len == 0) ,当value_len为0

sprintf(cookie, "Set-Cookie: %s=deleted; expires=%s", name, dt);
会发送删除cookie的http头给浏览器.

最后我们可以得出结论,在php中使用
setcookie($cookiename, '');或者 setcookie($cookiename, NULL);
都会删除cookie,当然这些手册中并没有。

Tags: 删除, cookie, 清空

向东的工作周报(2月 20 日-4月2日)

从名字可以看出来,这是向东的工作周报。不过,他的这一周,好长啊。。。其实是他每周的工作情况的简报啦。
这个习惯真好,我就没有养成。

他的第一个问题,我在以前与java那边交互的时候就遇到过,开始也是一直判断一直判断。最后发现获取的就是字符串,都跨语言了,还是用的curl来取值的,怎么可能传递布尔值?

最后它说的BOM问题,这就不太应该了。不过他的正则写得不错。我一直用editplus,文件选项里可是有一条:保存时始终去除BOM,就行了啦。用记事本,是会生成BOM的,微软的东西是差呀。。

框架这东西,仁者见仁智者见智,不多分析


原文如下:http://www.xiangdong.org/blog/post/1699/

近半年的工作心得,摘录如下:
(    2月 20 日--   2月  26  日)
工作心得
一.Ajax通过POST提交给$_POST数组变量问题:
和 js人员一块调试ajax提交一些数据的时候,在ajax调用的时候,js人员通过Post方式传给我一个'allowComment',它为 True\false,刚开始误以为是一个TRUE 或 FALSE是PHP里面的一个布尔值(实际是一个字符串),于是写下如下代码片段:
if(true ==  $_POST['allowComment'])
{
  $this->_par['allow_comment'] = 0;//0为允许评论

}else
{
  $this->_par['allow_comment'] = 1;
}
导 致出现无论post过来的数据是true还是false,只走if不走else,当时很奇怪,我通过print_r()来打印看到明明是false,但是 还是不走else这条路,最后听建鑫说它是个字符串,我于是改用var_dump()函数来看:var_dump($_POST)发现它其实就是个 string类型的字符串:string(4) "ture",不是布尔型的一个变量。而修改为:(引号引起来即可)
if(‘true’ ==  $_POST['allowComment'])
{
  $this->_par['allow_comment'] = 0;//0为允许评论

}else
{
  $this->_par['allow_comment'] = 1;
}
结论:尽管PHP是弱类型语言,但我们调试时候最好用var_dump(),而不是print_r();
二.DIV模板取高度自动适应的问题:
在 做这次记录套页面的时候,提供的页面是一整张页面,这就需要php工程师去去掉里面的一些没有用的DIV标签和多余的html代码,但是在把最后剩下的一 些HTML代码套好页面后,在放到pengyou里面测试时候,发现页面被遮挡,最后发现是由于刘嵩Js想取到一个DIV的高度没有得到正确的值,而这正 是由于HTML设计人员把一整张页面让PHP开发人员去从里面提取出需要的东西,但是往往会出现某些DIV没有带到Smarty页面里渲染,才导致js在 通过ID或者NAME去取高度时候出错,也就是PHP工程师套页面的时候并不知道UI提供的页面中哪些DIV是JS人员必须要的,而UI人员就把整个页面 给PHP工程师自己去剔掉多余的DIV和HTML,而刚好把JS需要的DIV给干掉了造成的.
结论:切页面得按照产品结构来,而不是仅仅UE,涉及到JS的得事先和PHP工程师和JS人员沟通。
三.接口变动问题:
一 些底层接口的变动往往造成输入(入数据库)和输出(如:页面)出现一些明显的逻辑错误,于是我们首先会想可能是不是程序逻辑出现了问题,进一步去查程序代 码的逻辑是否严密,会发现数据库里面出现一些和现实逻辑不同的情况,而很容易把陈脚搞乱,特别是有其它系统的介入,更让人很难发现其中错误。
结论:尽量少动接口返回的数据结构,保持结口稳定,而一旦改变,及时通知接口使用和开发方。

(    3月 6 日--   3月  12  日)

工作心得
对重构的一点体会:

1.改进软件的结构:
在开发记录的时候有时由于一个新的需求导致为了更快的满足用户,不故到程序的整体结构,而这种解决方法不能以一个系统的角度来解决问题,如果任其发展会使代码的质量越来越难以维护,而重构能改善这个问题。

2.增加可读性:
以 前的记录的数据层是由外包人员写的,让我觉得有点难懂,而有人说,修改别人的代码不如自己写,但事实上往往自己写的代码比上一个人还难以让别的人读懂,但 是如果这个人有一天离职或者没有上班那就有些耗费时间去读懂对方的代码,而我们的重构可以通过一些命名规范和类的规范和层次结构的规范来尽量防止这类事情 的发生,仅管我也参考了他们的代码。

3.及早地发现错误:
进行重构我们必须对项目的每一行代码的逻辑都了解,明确它的功能和上下程序调用关系,这样的理解我觉得有助于少犯错误和及时发现自己的错误。

4.提高了开发速度:
知道用户80%的需求的情况下,这种情况下重构,可能从一定程度上能提高开发速度。
(    3月 13 日--   3月  19  日)
遇到一问题
   在对记录的项目中进行重构的时候发现需要通过Ajax多提交一个POST变量到PHP那边去,发现不能随意加,而和js开发人员沟通了一下,结果是必须得 修改一下js代码,把多提交的一个加进去才行,但是我个人觉得js的Ajax Post应该做得像表单提交数据那样,只要多加一个数据<input type="text" value="add_value" name="XXX" id="XXX" />加入<form>
</form>表单,就可以对它POST提交到另一个PHP文件,而不是仅仅对一个单独的应用而写一个Ajax Post提交数据 ,不知能否改进成这样?

工作心得
1.
  做项目最好先了解需求,然后明确需求,再思考用例,然后画数据流,最后才是数据库的设计,当然最后的数据库设计也是最重要的!
2.
  对于一些定义分级和对应级别的少量数据最好放到PHP数组里面,而尽量不要放到数据库里,而对一些不是经常改动而却又是经常频繁查询用到的数据在量不是很在的情况下如放到数据库里面会显得成本太高,放到一个文本里变为一个配置文件来用效率可能会反而更高。
3.
  对 大并发和高访问的数据库设计解决方法现目前还是分表,如还不行,再Hash打散分库,但不能无限分,一个库尽量256表,动用4个库来也就分了1000个 表左右,建鑫的经验告诉这样可能性能和稳定性相对高一些,而不能随意乱分。不知按时间或者天数来分表这种情况会有什么样的问题,期待通过人缘项目来尝试一 下。


2009-03-20 ----2009-03-26:
遇到一问题
工作心得
对于上次邮件里面讨论到的PHP BOM问题,我来说来句就当心得吧,其实这个BOM问题一直在我们进行开发的时候经常出现,前些日子在企业邮箱里面第一次遇到这个问题,当时好像是企业的图标LOGO没有办法显示出来,因为<img alt="" src="http://www.xiangdong.org/blog/img.php" />,是img.php去读一个图片的内容然后给img显示,经过长仔细排查出现在输出图片资源前就有输出,那时候用的是notepad+editplus,最后用Zend studio来看这个文件头出现一个锘�字,证明了该问题。

第二次遇到BOM问题,是陈鑫鑫在纸条项目里面输出XML数据到IE浏览器中展现出现XML错误。

第三次也就是我们的记录APP调用外部接口返回用户的昵称出现乱码,经琳琳查也由BOM造成!
为 何经常出现这种类似的问题,我看大家都在按照自己的方式来建立和开发PHP,特别是用Notepad来新建文件,系统默认在是ANSI格式,但我们的 PHP编码是UTF-8的,于是又通过Notepad的另存为修改为UTF-8格式的,这样也就产生了一个BOM,最后,再用现在统一的开发工具Zend for eclipse去编辑这个带BOM的PHP文件,但BOM依然存在文件当中,它一般是表现不出任何问题,但一旦在页面前不能有输出的情况:如上面我遇到的 三种情况它也就显现出来了。

BOM如此讨厌,该如何避免:
建议:
1.  切实统一开发工具:统一用Zend for eclipse 来新建PHP文件,和修改PHP文件编码!
2.  在 项目完成后对目录里面所有的PHP 文件进行遍历驱出有可能出现的BOM。如:用sed批量替换掉bom:(syscore目录和所有下级目录的PHP文件替换)   find ./syscore -type f -name "*.php" -exec sed -i '1s/^\xef\xbb\xbf//' {}  \;



(3月27日---4月2日)
遇到一问题:
在调试记录的js时发现超过了页数却没有出现翻页导航的页,开始首先以为是数据没有输出程序的问题, 最后查明是由于朋友下面的frame把下面给档住了,Js人员修正了这个问题,这个问题还经常出现,希望js人员也多注意一下!
工作心得:
本周收到老姜发的一点对PHP框架的看法,我也斗胆也说说我自己对这个问题的看法,有些可能说得不太准确或者有些错误,还望包含:
首先,我个人是不反对PHP采用一些轻量级的框架,但极力反对对PHP用一些重型的框架的,为什么呢?因为它的执行方式决定了它的这个特点:php每一 个脚本先全部载入所有资源,执行完毕后全部放弃,所以使用太重的框架,会极耗内存和计算资源,形成调用栈太深占用系统资源,个人觉得轻量框架和简单的分层 还是一定要采用的。
其次,你会说像Java这样的语言它能采用一些的框架,而且还涌现出了一些红红火火的框架了呢:)
个人觉得那是因 为java的执行方式和PHP不一样,对于内存管理也不一样,有很多都是一次装入内存,直到jvm重启才被释放的, 事务性,安全性等等很多基础性的服务,都需要预先装入,何况java是基于工业级应用产生的,php只是个人网站开发才出现的,能一样吗?不能。所以,不 能我们也不要一边倒,看人家采用什么什么了,自己也想把PHP往边上套。
再次,C++和Java强悍的框架不少,但惨不忍睹的框架也更多,为 什么呢?用一个越是尖端的东西越不容易用好,对于重型的编程语言对软件工程功底的要求是相当高的,不是谁说想做个框架就做个框架,更何况各个项目的千差万 别,实际的情况也不尽一样,更不能以一个框架来以逸待劳,放大了框架的作用,它并不是万能的。
最后,我仅对PHP的框架也就领悟到:轻量框架和简单的分层还是PHP在大多数项目开发中还是一定要采用的,但切忌过重,把握好度,适可而止。

Tags: php, 经验

摘:精通php的十大要点

1. 在合适的时候使用PHP - Rasmus Lerdorf
没有谁比PHP的创建者Rasmus Lerdorf明白PHP用在什么地方是更合理的, 他于1995年发布了PHP这门语言,从那时起,PHP就像燎原之火,烧遍了整个开发阵营,改变了互联网的世界。 可是, Rasmus并不是因此而创建PHP的PHP是为了解决web开发者的实际问题而诞生的。

和许多开源项目一样,PHP变得流行,流行的动机并不能用正常的哲学来进行解释,甚至流行得有些孤芳自赏。它完全可以作为一个案例,一个解决各种web问题的工具需求所引起的案例,因此当PHP刚出现的时候,这种工具需求全部聚焦到PHP的身上。

但是,你不能奢望PHP可以解决所有问题。Lerdorf是第一个承认PHP只是一种工具的人,并且PHP也有很多力所不能及的情况。

根据工作的不同来选择合适的工具。我跑了很多家公司,为了说服他们部署和使用PHP,但是这并不意味着PHP对所有问题都适用。它只是可以一个解决大部分问题的front-end脚步语言。

作为一个web开发者,尝试用PHP解决所有问题是不科学的,同时也会浪费你的时间。当PHP玩不转的时候,不要犹豫,试用一下其他的语言吧。

2. 使用多表存储提高规模伸缩性 - Matt Mullenweg

没有人愿意质疑Matt Mullenweg在PHP方面的权威性,他开发了这个星球上最流行的blog系统,(依靠一个强大的社区力量支持): Wordpress. 创建Wordpress以后,Matt和他的团队启动了Wordpress.com平台,一个基于Wordpress MU的免费blog站点。现在,Wordpress.com已经拥有大约400万用户, 这些用户每天提供超过 140,000篇的日志。 (要查看更多Wordpress.com的统计情况,请点击这里.)

如果有人知道如何让网站的规模伸缩自如,这个人一定是Matt Mullenweg。2006年的时候 Matt对Wordpress的数据结构进行了前瞻性的改进,并且解释了为什么Wordpress MU对每个blog使用独立的MYSQL表格, 而不是把所有的blog数据都塞进一个巨大的表格。

我们测试过这个方法,但是发现如果要扩展它的伸缩性,代价太高。如果用一个整体的数据结构,在大流量面前,你将会面临服务 器硬件的问题。在MU里面。用户们都被分布到独立的表格当中,并且可以轻易地组织起来。举个例子,WordPress.com把用户的数据分散存储到 4096个数据库中,这些数据库可以分散大规模的数据访问,实现流量和压力分流。

数据表的可迁移性让代码(blog)可以运行得更快,并且让系统具备更强的伸缩性。依靠强大的缓存策略和灵活的数据库运用策略, Matt向人们展示了时下最流行的Facebook和Wordpress.com都可以在PHP下稳定运行,并且处理惊人的访问量。

3. 千万不要相信用户 - Dave Child

Dave Child是 Added Bytes (previously ilovejackdaniels.com) 网站的核心人物,这个网站以他出色的《cheat sheets for many programming languages》而闻名。 Dave为很多英国的公司服务,并且已经在编程世界里树立起相当的权威。

Dave为PHP开发者提供了很多深谋远虑的建议,并总结成了《writing secure code in PHP》:千万不要相信你的用户,他们甚至可能会伤害你。

有一条web开发的基本原则,我重复多少遍都觉得不够,那就是:千万不要相信你的用户,同时要假设你网站中的每个数据单元 都是从用户那里收集来的恶意代码。很多时候,你必须用javascript在客户端检验表单提交过来的内容, 如果你习惯了如此,那么,这是一个好习惯。如果安全性对你来说很重要,这就是最重要最需要学习的原则。

Dave目前正致力于为它的《Writing Secure PHP》系列书籍整理实例,书的最后他说:

最后,变得偏执一点吧。除非你认为你的站点永远不会受到攻击,否则就正视所有的问题,当问题真正发生的时候,你的情况会变得很糟。你需要把每个用户都看成会带来一场攻防站的黑客,想尽一切办法来保护站点的安全,同时想好相应问题的解决方案。

4. 多使用PHP缓存 - Ben Balbo

Ben Balbo开发了Site Point,一个为developers和designers提供指导的网站。他是墨尔本PHP开发和开源俱乐部的成员, 因此他对PHP有一定的了解,同时对PHP caching有一定的想法和经验。

如果你拥有一个访问量很大,但更新并不频繁的站点(比如blog,基于某种CMS),或许它需要进行一些改造,这些改造不会花费太多的时间,但是对性能有突出的贡献。 如果要为一个复杂/更新频率很快的站点建立缓存机制,过程可能会很曲折,但是好处也是显而易见的。

PHP缓存技术有很多种,Ben为我们推荐了如下一些:

缓存函数的运行结果
设置过期时间
缓存IE下载的文件
模板缓存技术
Cache_Lite

由于PHP作为动态语言的特性,缓存机制对于更新频率并不快的站点来说非常重要。

5. 使用IDE, Templates和Snippets加速PHP开发 - Chad Kieffer

当Chad Kieffer从UI设计和数据库优化的工作中抽身出来的时候,他会在他的博客2 tablespoons上分享很多技术经验。由于Chad多方面的全面发展,他经常可以发现其他程序员不能发现的问题,并形成相关经验,尤其是他开发网站的方法。他参与了网站开发的各个环节,因此他的建议对于提高网站开发的大局观非常有用。

Chad认为使用Eclipse PDT
(Eclipse’s PHP development package) 这样的IDE,同时使用一些模板技术和开源项目可以有效地提高PHP的开发速度。

紧凑的计划,长长的to do lists以及deadlines让开发人员非常苦闷。不过有些功能,比如Eclipse Templates,可以有效减少编码的时间和出错的几率。

通常来说,任何项目都可以自动化,自动化程度越高, 你完成项目的时间就越短。花时间来开发使用频率很高的框架和模板,将会节省你以后更多时间。同时,使用像Eclipse and the PDT package这样的IDE,你会发现效率得到明显提高,IDE可以自动闭合,补全分号并且可以在本地debug。

6. 利用好PHP的过滤函数 - Joey Sochacki

或许Joey Sochacki并不像Matt Mullenweg那样有名 ,但他也是一个经验丰富的开发者,并且通过他的博客Devolio分享了很多技术经验

Joey发现在编写php代码的过程中有很多地方需要进行过滤,但却并没有太多的coder关注php的内置过滤函数。

过滤数据是我们经常需要做的事情,但是很多功能丰富的PHP内置过滤函数却不为人知。使用类似filter_* 的PHP内置函数,我们几乎可以处理所有的过滤任务,包括数据类型验证/URL/email和IP地址验证/特殊字符处理等等。

过滤是一件复杂的事情,但是我相信joey的发现会给你很多启发,让你认识到PHP强大的过滤功能。
7. 使用PHP框架 - Josh Sharp

对于是否应该使用Zend, CakePHP, Code Igniter, 或者 其他PHP框架,一直存在着很多争议,但是在web开发者的心中,他们有自己衡量的标准。

Josh Sharp自己创建了一家提供面包和黄油服务的网站,因此他对于使用PHP框架来开发网站有一定的经验。他认为使用一个PHP框架来进行项目开发(use a PHP framework ),可以有效地节省时间,并且减少出错的几率。为什么?因为他觉得PHP实在是太好上手了。

PHP的易于使用有时候也有缺陷,因为并不严格的语法,经常会导致很多错误代码的诞生。但如果使用一个PHP框架,出错的几率就会大大减少。

PHP框架可以让你的代码结构更加规范,并且节省大量时间,你可以阅读《 benefit of using a PHP framework 》来获得更多相关信息。

8. 不要使用PHP框架 - Rasmus Lerdorf

与Josh的观点恰恰相反, PHP的鼻祖Rasmus Lerdorf却认为最好不要使用PHP框架,为什么?因为不基于框架的PHP性能更好。

Rasmus在Drupalcon 2008的演讲上,用“Hello World”的例子来对比了一些框架PHP和简单PHP之间的性能,结果显示框架PHP的性能要远远落后。

9. 使用批处理 - Jack D. Herrington

Jack Herrington对PHP世界并不陌生, 并且为大名鼎鼎的IBM developerWorks贡献过超过30篇的专搞, 同时出版过《PHP Hacks》的书,因此他是一个真正的专家。

Herrington 推荐使用批处理和Cron来代替那些可以运行在后台的程序脚步,web用户并不愿意在线等待你的处理过程,所以有些事情更适合放到后台来处理。

诚然,在某些情况下,这有点大材小用了,但是你可以清楚地看到,使用Cron, MySQL, PHP面向对象的方法以及Pear::DB这些便捷的工具来创建一个批处理工具并不是一件复杂的事情。

Jack认为使用cron, PHP和MySQL在后台处理一些任务,比起多进程的业务逻辑要划算得多。

两种方法我都尝试过,我认为Cron非常符合”Keep It Simple, Stupid” (KISS) 的原则,它让后台处理变得简单。与多进程的业务逻辑相比,它没有内存溢出的风险。你可以创建一个简单的批处理脚本,并且在cron中运行,这个脚本会定时 检查是否有任务需要处理,处理完之后就会自动退出,因此你不用担心是否有进程卡壳,或者陷入死循环。

10. 及时启用错误报告 - David Cummings

David Cummings有一个专门提供CMS软件服务的公司 ,并且获得过几次奖 ,他有非常丰富的PHP开发经验。

David曾经写过《two PHP tips he wished he’d learned in the beginning》,其中一点就是:及时启用错误报告,这会节省大量的时间。

我告诉人们,最重要的事情就是最大程度地开启PHP的错误报告,为什么?因为PHP可能会隐藏很多小问题:

  • 变量没有预定义
  • 在代码片段中引用了不可用的变量
  • 使用了未定义的常量
  • 这些因素看起来并不是什么大事,除非你在使用面向对象的方法编写一些类库。通常,关闭错误报告将可能使你付出更大的成本来维护你的代码。

错误报告可以帮你轻易地找到代码的问题所在,如果错误报告的等级够高,细微的错误都能被立即发现,帮助你节省整体debug的时间。
原文地址:http://nettuts.com/tutorials/php/10-principles-of-the-php-masters/
翻译整理:Andrew

Tags: 精通, php