《PHP最佳实践》由会员分享,可在线阅读,更多相关《PHP最佳实践(32页珍藏版)》请在金锄头文库上搜索。
1、P H P最佳实践(译)J u n 0 1 , 2 0 1 3原文:P H P B e s t P r a c t i c e s - A s h o r t , p r a c t i c a l g u i d e f o r c o m m o n a n d c o n f u s i n gP H P t a s k s译者:y o u n g s t e r x y f最后修订日期&维护者本文档最后审阅于2 0 1 3年3月8日。最后修改于2 0 1 3年5月8日。由我,A l e x C a b a l,维护该文档。我编写P H P程序已有很长一段时间了,当前我经营着S c r
2、i b o p h i l e,由认真作家组成的一个在线写作团体, W r i t e r f o l i o,为自由职业者提供的一个易用写作工具集,以及S t a n d a r d E b o o k s,一个图文并茂、无数字版权管理的公共领域电子书出版商。有时我是个为吸引我的项目或客户而工作的自由职业者。如果你认为我在某些事情上能够帮到你,或者对本文档有点建议或纠正存在的错误,请给我写封邮件。简介P H P是一门复杂的语言,经过多年折腾,使其不同版本之间高度不一致,有时还有些b u g。每个版本都有自己独有的特性、多余和怪异之处,也很难跟踪哪个版本有哪些问题。这也就很好理解为什么有时它会
3、遭到那么多的厌恶。尽管如此,如今它还是W e b开发方面最流行的语言。因其悠久的历史,对于实现密码哈希和数据库访问诸如此类的基本任务你能够找到很多教程。但问题在于,5个教程,你就很有可能找到5种完全不同的完成任务的方式,那么哪种是“正确”的方式呢?其他方式有难以捉摸的b u g或者陷阱?确实很难搞明白,所以你经常要在互联网上反复查找尝试确认正确的答案。这也是P H P编程新手频繁地因为丑陋、过时、或不安全的代码而遭到责备的原因之一。如果G o o g l e搜索的第一个结果是一篇4年前的文章,讲述一种5年前的方法,那么P H P新手们也就很难改变经常遭受责备的现状。本文档通过为P H P中常见
4、的令人困惑的问题和任务编辑组织一系列被认为最佳实践的基本做法,来尝试解决上述问题。若一个低层次的任务在P H P中有多种令人困惑的实现方式,本文也会涵盖。是什么这是一份指南,在P H P程序员遇到一些常见低层次任务但不明确最佳做法(由于P H P可能提供了多种解决方案)之时,为其建议最佳实践。例如:连接数据库是一个常见任务,P H P中提供了大量可行的方案,但并不是所有的都是好的做法,因此,本文也会包含该问题。本文包含的是一系列简短的、入门性质的方案。涉及的示例在基本设定下就能够运行起来,你研究一下应该就能把它们变为对你有用的东西。本文将指出一些我们认为是P H P中最新最好的东西。然而,这意
5、味如果你在使用老版本的P H P,一些用来实现这些解决方案的特性对你并不可用。这份文档会一直更新,我会尽我最大努力保持该文档与P H P的发展同步。不是什么本文档不是一份P H P教程。你应该在别处学习语言基础和语法。它也不是一份针对w e b应用常见问题,如c o o k i e存储、缓存、编程风格、文档等的指南。它也不是一个安全指南。当本文档触碰到一些安全相关的问题时,也是希望你自己做些研究来确保你的P H P应用的安全问题。你的代码造成的问题应该都是自己的过错。该文档也并不是在主张一种特定的编程风格、模式或者框架。也不是在主张一种特定的方式来完成高层次任务如用户注册、登录系统等。本文档只
6、限于P H P的悠久历史所造成的一些易混淆或不明确的低层次任务。它不是一个一劳永逸的解决方案,也不是一个唯一的方案。下面要讲述的一些方法对于你的特定场景来说也许并不是最好的,存在很多不同的方式来达到同样的目的。特别是,高负载w e b应用也许能从更加难懂的方案中获益更多。我们在使用哪个版本的P H P?带S u h o s i n - P a t c h的P H P 5 . 3 . 1 0 - 1 u b u n t u 3 . 6,安装在U b u n t u 1 2 . 0 4 L T S上。P H P是W e b世界里的百年老龟,它的壳上铭刻着一段丰富、复杂、而粗糙的历史。在一个共享主机
7、的环境里,它的配置可能会限制你能做的事情。为了保持清晰地叙述,我们将仅针对一个版本的P H P进行讲述。在2 0 1 3年4月3 0日时,该版本为P H P 5 . 3 . 1 0 - 1 u b u n t u 3 . 6 w i t h S u h o s i n - P a t c h。若你在U b u n t u1 2 . 0 4 L T S服务器上使用a p t - g e t进行安装的就是该版本的P H P。你也许发现这些方案中的一些在其他或者更老版本的P H P上也能工作。如果是这样的话,就由你来研究在这些更老版本上潜在的难以捉摸的b ug或安全问题。存储密码使用p h p a
8、s s库来哈希和比较密码经p hpa s s 0. 3测试在存入数据库之前进行哈希保护用户密码的标准方式。许多常用的哈希算法如m d 5 ,甚至是s h a 1对于密码存储都是不安全的,因为骇客能够使用那些算法轻而易举地破解密码。对密码进行哈希最安全的方法是使用b c r y p t算法。开源的p h p a s s库以一个易于使用的类来提供该功能。示例Has hPass word( my s uper cool pass word ) ;/ Yo u can now s afel y s tore the contents of $has hedPass word i n your data
9、base!/ Check i f a us er has pr ovi ded the cor rect pas s word by compari ng what they/ typed wi t h our has h$has her-CheckPass word( the wr ong pas swor d, $has hedPas swor d) ; / fal s e$has her-CheckPass word( my s uper cool pass word , $has hedPas s word) ; / tr ue?陷阱许多资源可能推荐你在哈希之前对你的密码“加盐”。想法
10、很好,但p h p a s s在H a s h P a s s w o r d ( )函数中已经对你的密码“加盐”了,这意味着你不需要自己“加盐”。进一步阅读 p h p a s s为什么使用m d 5或s h a哈希密码是不安全的怎样安全地存储密码连接并查询M y S Q L数据库使用P D O及其预处理语句功能。在P H P中,有很多方式来连接到一个M y S Q L数据库。P D O(P H P数据对象)是其中最新且最健壮的一种。P D O跨多种不同类型数据库有一个一致的接口,使用面向对象的方式,支持更多的新数据库支持的特性。你应该使用P D O的预处理语句函数来帮助防范S Q L注入攻
11、击。使用函数b i n d V a l u e来确保你的S Q L免于一级S Q L注入攻击。(虽然并不是1 0 0 %安全的,查看进一步阅读获取更多细节。)在以前,这必须使用一些“魔术引号( m a g i c q u o t e s ) ”函数的组合来实现。P D O使得那堆东西不再需要。示例PDO: : ERRMODE_EXCEPTI ON,PDO: :ATTR_PERSISTENT = f a l s e,PDO: :MYSQL_ATTR_I NIT_COMMAND = set names utf8mb4) ;$handl e = $l i nk-pr epare( s el ect
12、Us er name fr om Us ers wher e Us erI d = ? or Us ername = ?l i mi t ? ) ;/ PHP bug: i f you don t s peci fy PDO: : PARAM_I NT, PDO may encl os e the argument i n quotes./ Thi s can mes s up s ome MySQL quer i es that don t expect i nteger s to be quoted./ See: htt ps : /bugs. php. net/bug. php?i d=
13、44639/ I f you r e not s ur e whet her the val ue you re pass i ng i s an i nteger, us e the i s _i nt ( ) funct i on.$handl e-bi ndVal ue ( 1, 100, PDO: : PARAM_I NT) ;$handl e-bi ndVal ue ( 2, Bi l bo Baggi ns ) ;$handl e-bi ndVal ue ( 3, 5, PDO: : PARAM_I NT) ;$handl e-execute ( ) ;/ Us i ng the
14、fetchAl l ( ) method mi ght be too r esour ce-heavy i f you r e s el ecti ng a tr ul y mas si veamount of r ows ./ I f that s the case, you can us e the fetch( ) method and l oop thr ough each r es ul t r ow one byone./ You can al s o r etur n arr ays and other thi ngs i ns tead of obj ects . See th
15、e PDOdocumentati on for detai l s .$r esul t = $handl e-fetchAl l ( PDO: : FETCH_OBJ) ;f o r e a c h( $r esul t a s $r ow) p r i n t( $r ow-Us ername) ;c a t c h( PDOExcepti on $ex) p r i n t( $ex-getMess age( ) ) ;?陷阱当绑定整型变量时,如果不传递P D O : : P A R A M _ I N T参数有事可能会导致P D O对数据加引号。这会搞坏特定的M y S Q L查询。查
16、看该b u g报告。未使用 s e t n a m e s u t f 8 m b 4 作为首个查询,可能会导致U n i c o d e数据错误地存储进数据库,这依赖于你的配置。如果你绝对有把握你的U n i c o d e编码数据不会出问题,那你可以不管这个。启用持久连接可能会导致怪异的并发相关的问题。这不是一个P H P的问题,而是一个应用层面的问题。只要你仔细考虑了后果,持久连接一般会是安全的。查看S t a c kO v e r f i l o w这个问题。即使你使用了 s e t n a m e s u t f 8 m b 4 ,你也得确认实际的数据库表使用的是u t f 8 m b 4字符集!可以在单个e x e c u t e ( )调用中执行多条S Q L语句。只需使用分号分隔语句,但注意这个b u g,在该文档所针对的P H P版本中还没修复。进一步阅读 P H P手册:P