因为 @公子 公子指出了我在一个 回复 中的错误,我才开始逐渐意识到自己已经开始养成了一些很不好的编程习惯,比如嵌套循环,比如 N
多个条件嵌套,导致 }
符号堆积,以至于代码可读性极差。之前只重视了功能的实现与否,没有忽视了代码的可读性和性能方面的体现。
这边罗列下我所知道的一些不好的编程习惯:
1.嵌套循环
2.过多的条件嵌套
3.用户提交数据不进行过滤
4.函数体过长
5.变量命名清晰
我相信有不少 PHPer
都读过 《PHP 最佳实践》,或许我们大家可以集思广益,总结一个《PHP“最差”实践》,这样也可以当做一个警示录,时刻提醒自己优化代码,希望 PHP
开发经验丰富的前辈们能不吝赐教。:)
因为 @公子 公子指出了我在一个 回复 中的错误,我才开始逐渐意识到自己已经开始养成了一些很不好的编程习惯,比如嵌套循环,比如 N
多个条件嵌套,导致 }
符号堆积,以至于代码可读性极差。之前只重视了功能的实现与否,没有忽视了代码的可读性和性能方面的体现。
这边罗列下我所知道的一些不好的编程习惯:
1.嵌套循环
2.过多的条件嵌套
3.用户提交数据不进行过滤
4.函数体过长
5.变量命名清晰
我相信有不少 PHPer
都读过 《PHP 最佳实践》,或许我们大家可以集思广益,总结一个《PHP“最差”实践》,这样也可以当做一个警示录,时刻提醒自己优化代码,希望 PHP
开发经验丰富的前辈们能不吝赐教。:)
1,拼凑SQL,如下
<code class="lang-php"> $sql = "INSERT INTO `#@__archives`(id,typeid,typeid2,sortrank,flag,ismake,channel,arcrank,click,money,title,shorttitle, color,writer,source,litpic,pubdate,senddate,mid,voteid,notpost,description,keywords,filename,dutyadmin,weight) VALUES ('{$this->art['id']}','{$this->art['typeid']}','{$this->art['typeid2']}','{$this->art['sortrank']}','{$this->art['flag']}', '{$this->art['ismake']}','{$this->art['channelid']}','{$this->art['arcrank']}','{$this->art['click']}','{$this->art['money']}','{$this->art['title']}', '{$this->art['shorttitle']}','{$this->art['color']}','{$this->art['writer']}','{$this->art['source']}','{$this->art['litpic']}','{$this->art['pubdate']}', '{$this->art['senddate']}','{$this->art['adminid']}','{$this->art['voteid']}','{$this->art['notpost']}','{$this->art['description']}', '{$this->art['keywords']}','{$this->art['filename']}','{$this->art['adminid']}','{$this->art['weight']}');"; </code>
2, 迟迟不肯return,代码挤在一起
<code class="lang-php">function readHosts(){ global $config; $hosts = array(); $fp = fopen(HOST_FILE, 'r'); if($fp){ while(!feof($fp)){ $line = trim(fgets($fp)); if($line!='' && substr($line, 0, 1)!='#'){ //将多个空格替换为一个,增加容错率 $line = preg_replace("/\s(?=\s)/","\\1",$line); @list($host,$user,$password,$time) = explode(' ', $line); $timeline = mktime((int)$time); if($host && $user && $password){ if($timeline $host, 'dbuser' => $user, 'dbpwd' => $password, 'dbname' => 'mysql', 'dbprefix' => 'dede_', 'dbcharset' => 'gbk', ); msg('服务器'.$host.'加入发布列队'); }else{ msg('服务器'.$host.'没有到发布的时间'); } } } } echo "\r\n"; } fclose($fp); return $hosts; } </code>
3, 全局变量global, 以下的msg
函数大量调用....
<code class="lang-php">function SendToSite($site){ global $db,$log,$config; if($log->get_value($site['dbname'])==='finish') return; echo "=====================\r\n"; msg('开始连接到数据库 '.$site['dbname']); if($db->select_db($site['dbname'])){ msg('连接成功,收集站点信息'); if($db->HasTable('archives')){ msg('找到文章数据表,开始发布'); }else{ msg('没有找到文章数据表,可能表前缀不正确,跳过这个站点'); return; } }else{ msg('连接失败,跳过这个站点'); return; } </code>
4,超长嵌套
<code class="lang-php"> if(count($site_channel)>0) { $keylink = '<a href="'.%24site_url.'" target="_blank">'.GBKTOUTF8($site_name).'</a>'; msg('找到'.count($site_channel).'个文章栏目'); echo "\r\n"; foreach ($site_channel as $channel){ if($log->get_value($site['dbname'].'_'.$channel['id'])==='finish'){ msg($site['dbname'].'栏目ID为'.$channel['id'].'今日已发布完成,跳过'); continue; } $sendnum = ReadIntFromStr($config['send_num']); if($sendnum get_value($site['dbname'].'_'.$channel['id'])){ continue; } $keyword_title_num = ReadIntFromStr($config['keyword_title_num']); if($keyword_title_num>$sendnum) $keyword_title_num = $sendnum; $keyword_titles = array(); for($i=0;$iget_value($site['dbname'].'_'.$channel['id']);$iart_add($art)){ $backupfile=DIR_BACKUP.substr($txtfile, strlen(DIR_TXTFILE)); if(!file_exists(dirname($backupfile))) mkdirs(dirname($backupfile)); rename($txtfile, $backupfile); msg('添加成功,备份txt文件'); $log->add($site['dbname'].'_'.$channel['id'], $i); $log->save(); }else{ msg('文章添加失败'); } }else{ msg('向 ['.$channel['typename'].'] 中添加文章失败,跳过'); continue; } }else{ msg('没有找到可用的txt文件'); break; } echo "\r\n"; } $log->add($site['dbname'].'_'.$channel['id'], 'finish'); $log->save(); } $log->add($site['dbname'], 'finish'); $log->save(); }else{ msg('没有找到文章栏目,跳过这个站点'); echo "\r\n"; } </code>
5, 过多使用@
抑制错误,不使用异常处理, 类的方法没有明确声明访问权限.
<code class="lang-php">class db { private $config = array( 'dbhost' => '', 'dbname' => '', 'dbuser' => '', 'dbpwd' => '', 'dbprefix' => '', 'dbcharset' => '' ); public $linkID = null; public $isconnect = FALSE; function __construct($config) { $this->config = $config + $this->config; $this->connect(); } function connect(){ if($this->config['dbhost'] && $this->config['dbname']){ $this->linkID = @mysql_connect($this->config['dbhost'], $this->config['dbuser'], $this->config['dbpwd']); if(!$this->linkID){ //连接错误,直接退出 //echo mysql_error()."\r\n"; return FALSE; } if (@mysql_select_db($this->config['dbname'])) { if($this->config['dbcharset'] != ''){ @mysql_query("SET NAMES '{$this->config['dbcharset']}'", $this->linkID); } } $this->isconnect = TRUE; } return $this->isconnect; } } </code>
太多了..不好弄...
https://github.com/justjavac/PHP-Best-Practices-zh_CN
http://youngsterxyf.github.io/2013/06/01/php-best-practices/
http://segmentfault.com/a/1190000000443795
http://wulijun.github.io/php-the-right-way/
http://thisinterestsme.com/php-best-practises/
没仔细看,可能有重复。
常规的别人都会说,我来说点激进的吧
<code>$arr = array(); for($i = 0; $i </code>
避免上面这种写法,因为循环每一次都会重新计算一次数组长度,可以这样写:
<code>$arr = array(); $length = count($arr); for($i = 0; $i </code>
之前翻译过一个针对新手的建议帖子 一共有三篇
其中前两篇有比较多的对于不好用法的分析和解决方案
http://ashitaka.me/%E8%AF%91/2014/01/05/40-php-tips-part-i/
http://ashitaka.me/%E8%AF%91/2014/01/06/40-php-tips-part-ii/
拿自己举例,一个实现合并二维数组相同 key
的写法:
我的 ugly
写法:
<code>$arr1 = array( array('num'=>5,'period'=>3), array('num'=>10,'period'=>3), array('num'=>15,'period'=>9) ); $arr2 = array(); foreach($arr1 as $k1 => $v1) { if(empty($arr2)) { $arr2[] = $v1; } else { foreach ($arr2 as &$v2) { if($v1['period'] == $v2['period']) { $v2['num'] += $v1['num']; } else { $arr2[] = $v1; } } } } </code>
1.不必要的嵌套循环
2.变量命名不清晰
3.}
堆叠使得代码可读性极差
@公子 的规范写法:
<code>rr = array( array('num'=>5,'period'=>3), array('num'=>10,'period'=>3), array('num'=>15,'period'=>9) ); $temp = array(); foreach($arr as $item) { list($n, $p) = array_values($item); $temp[$p] = array_key_exists($p, $temp) ? $temp[$p]+$n : $n; } $arr = array(); foreach($temp as $p => $n) $arr[] = array('num'=>$n, 'period'=>$p); print_r($arr); </code>
1.拆开循环
2.利用 PHP
自带的数组函数简化了代码
3.代码可读性较强
如果你用netbeans8.0的话,超过2还是3层的嵌套,全局变量的不经判断直接使用,一个方法写的太长(应该对功能拆分).等等,都会直接给出警告提示.一个好的IDE对提高自己的代码书写规范性和可阅读新还是很有帮助的.
慎用&
例子:
<code>$arr = array('a'=>1, 'b'=>2); foreach($arr as &$v) { if($v == '2') { $v = 3; } } $v = 444; </code>
打印$arr['b'] 的值为 444;
可以改成如下:
<code>$arr = array('a'=>1, 'b'=>2); foreach($arr as $k => $v) { if($v == '2') { $arr[$k] = 3; } }</code>
某些字符串函数与数组函数搞不清哪个是needle哪个是haystack...
js里有一种嵌套回调,层级太深了,也是巨难理解的。不过写过js的人都习惯了……
你贴的代码,之所以难读,好像和缺少换行和注释也有关系。