设计模式在代码和项目中使用常见模式是有好处的,可以让代码更易于管理,同时也便于其他开发者理解你的项目。 如果你的项目使用了框架,那么在代码和项目结构上,都会遵循框架的约束,自然也就继承了框架中的各种模式, 这时你所需要考虑的是让上层代码也能够遵循最合适的模式。反之,如果没有使用框架,那么就需要你自己选择 适用于当前项目类型和规模的最佳模式了。 异常异常是大部分流行语言的标准特性,但是PHP开发者却不太重视。其他语言如 Ruby极度倚赖异常,在任何错误发生的时候,如HTTP请求失败 、DB查询错误,甚至图片资源未找到,都会抛出一个异常,以及时提示那里发生了一个错误。 PHP则对此很宽松,如调用 这种做法的另外一个弊端是当类自动在屏幕打印一个错误,然后退出进程,阻止了其他开发者动态处理该错误的机会。而异常则是让开发者知道 发生了错误,并让他们选择如何处理:
SPL异常默认的异常类Exception包含的上下文信息很少,对于debug不方便,常见的做法是创建更具体的子类:
这使得你可以包含多个catch子句来处理不同的异常,但是这又会导致创建_很多的_自定义异常类,可以用SPL中的异常类来缓解这个问题 SPL扩展. 如使用 数据库通常PHP代码使用数据库来持久化存储数据,并有多种方式去连接和操作数据库。在_PHP 5.1.0_之前,推荐的方式有mysql、 mysqli和pgsql等。 如果应用只是使用一个数据库的话,原生驱动就工作的非常好,否则使用MySQL的同时,还需要使用MSSQL或Oracle数据库的话,那么 就没有办法只使用一个原生驱动了,只能分别学习各个数据库驱动的API,这非常令人生厌。 另外需要注意,mysql这个原生驱动已经不在活跃开发状态了,从PHP 5.4.0开始被标记为不推荐使用,意味着将来版本如PHP 5.6可能会 移除这个扩展。如果你正在使用 PDOPDO是数据库连接抽象库,从PHP 5.1.0开始提供,提供多种数据库的统一的操作接口。PDO不会转化你的SQL查询或者模拟缺失特性; 它只是提供统一的API去连接不同的数据库而已。 更重要的是, 假设PHP脚本接收一个数字ID作为查询参数,从数据库取回一条记录。下面是一种错误的做法:
这是非常糟糕的代码,直接在SQL中插入一个原始输入变量,导致潜在的SQL注入风险。假如黑客构造URL:
这才是正确的代码,在PDO statement中绑定一个参数,使得查询被发给数据库之前,对输入参数进行转义,防止SQL注入攻击。 另外一个要注意的问题是,如果数据库连接没有隐式地关闭,那么数据库连接数可能会超过数据库服务器的限制而连接失败,这种 错误在其他编程语言中比较常见。PDO对象在销毁的时候会隐式的关闭数据库连接,只要你把指向它的引用全部删除即可,如设置 为NULL。如果没有,PHP也会在脚本结束时关闭所有非持久化的数据库连接。 抽象层很多框架都提供了自己的数据库抽象层,有的是基于PDO,有的不是。它们通过PHP方法来包装实际的查询,能够模拟出只存在于 某些数据库系统的特性,给你一个真正的数据库抽象层。这么做会带来一些性能的损失,但是在一个需要支持MySQL、PostgreSQL 和SQLite的应用中,这个损失相对于由此带来的代码一致性而言是可以接受的。 有些抽象层遵循PSR-0命名空间标准,可以集成在任意的应用中: 安全Web应用安全总有一些人会千方百计的想着破坏你的Web应用,提前想办法加强自己的Web应用的安全性非常重要。幸运的是, The Open Web Application Security Project (OWASP) 已经提供详尽的已知安全问题列表和防范对策。 每个关注Web安全的开发者都应该仔细阅读该列表。 Password HashingEventually everyone builds a PHP application that relies on user login. Usernames and passwords are stored in a database and later used to authenticate users upon login. It is important that you properly hash passwords before storing them. Password hashing is an irreversible, one way function performed against the users password. This produces a fix length string that can not be feasibly reversed. This means you can compare a hash against another to determine if they both came from the same source string, but you can not determine the original string. If passwords are not hashed and your database is accessed by an unauthorized third-party, all user accounts are now compromised. Some users may (unfortunately) use the same password for other services. Therefore, it is important to take security seriously. Hashing passwords with In PHP 5.5 Below we hash a string, we then check the hash against a new string. Because our two source strings are different (‘secret-password’ vs. ‘bad-password’) this login will fail.
数据过滤永远不要在PHP代码中信任外部输入,在使用之前一定要先过滤和验证, 外部输入可以是: 当外部数据被存储合并之后,下次读取时,它们仍然算是外部输入,每次在代码中处理的时候,需要问自己是否已经正确过滤,是否可以 信任它们。 数据需要根据不同用处,进行不同的_过滤_,如果把未经过滤的数据输出到HTML页面,它可以在你的网站里执行HTML和JavaScript!即通常 说的跨站脚本攻击(XSS)。避免XSS的一个策略就是使用 另外一个例子是传给命令行命令的选项,这可能非常危险(通常不是一个好主意),不过你可以用内置的 最后一个例子是根据外部输入来从文件系统中加载文件的操作,可以通过修改路径中的文件名实施攻击。你需要过滤输入中的”/”, “../”, null bytes, 或其他特殊字符,以防止加载不能公开的包含敏感数据的文件。 数据清洗数据清洗就是删除或转义外部输入中的非法或不安全字符。比如把外部数据输出到HTML或插入到SQL语句之前,需要先清洗外部输入。 当你通过PDO绑定数据时,它会替你转义输入数据。 有时候需要允许外部数据包含安全的HTML标签,并输出到HTML页面中。这个比较难处理,可以考虑使用其他更严格的格式,如 或BBCode,实在不能的话,可以使用HTML Purifier库来进行数据清洗。 数据验证数据验证外部输入就是你预期的,如你在处理注册表单时,需要验证email地址、电话号码和年龄等数据 配置文件在创建应用的配置文件时,请遵循下面的业界最佳实践:
注册全局变量提示:从PHP 5.4.0开始, 启用 例如: 错误提示错误日志可以帮助追查应用的Bug,但是也会暴露应用的结构信息而产生安全问题,为此,需要在开发环境和线上环境设置不同的配置,防止 敏感信息的泄漏。 开发环境要在开发环境显示错误提示,需要在
来自php.net:
各PHP版本显示所有错误的配置
线上环境要在线上环境隐藏错误提示,需要在
这样设置后,线上错误会记录到Web服务器的错误日志中,而不是直接显示给用户。如果想了解更多错误提示相关的设置,请参考手册: 测试为PHP代码编写自动化测试被认为是一个最佳实践,可以帮助你构建出高质量的应用。自动化测试可以帮助你确认没有因为重构或添加 新功能而破坏原有功能,所以应该重视自动化测试。 PHP有多种类型的测试工具和框架可以使用,具体方法各有区别——但是它们的目标都是避免手工测试,满足大型QA组织的需求,保证最新的 更改没有破坏已有功能。 测试驱动开发Wikipedia的定义:
目前对应用有多种类型的测试: 单元测试单元测试是从编写开始,贯穿于整个开发周期的一种用于保证函数、类和方法的行为与预期一致的编程方法。通过检查各个函数和方法的输入和输出值,你可以保证它们 内部逻辑已经正确执行;通过依赖注入、编写mock类和stubs,你可以验证依赖是否已经正确处理,提高测试覆盖率。 在编写一个类或函数的时候,应该为它的每一个行为创建一个单元测试,至少你要保证它收到错误参数时能够触发错误,而参数正确时能正常工作。这可以帮你在后面 修改类或函数的时候,确认已有功能仍然正常工作。PHP中var_dump()的功能与此类似,但是它是无法用于创建应用的。 单元测试的另外一个用武之地是在给开源项目贡献代码时,如果你编写一个测试,证明代码存在bug,然后修复代码,让测试通过,这样该补丁被接受的概率要高很多。 如果你的项目接受人家的补丁,你应该把单元测试作为项目的一项要求。 PHPUnit是PHP应用的单元测试框架的业界标准,其他几个可选框架是: 集成测试Wikipedia的定义:
很多单元测试工具同时也可以用于集成测试,并且原理也是相通的。 功能测试有时也称为验收测试,使用工具创建自动化的测试用例,然后在真实的系统上运行,这一点与单元测试验证单个模块的正确性和集成测试验证模块间交互的正确性是有 区别的,这些工具通常使用真实的数据集来模拟真实用户的使用行为来验证系统的正确性。 功能测试工具
|