modern php 笔记(第一次阅读)
modern php
特性
- php性状:使两个无关的php类具有类似的行为
- php生成器 yield :生成器是简单的迭代器
- 闭包和匿名函数 在php中是Closure类的实例(在php中将闭包和匿名函数等同了),可以使用$this关键字获取宾傲的内部状态
- 将php闭包当做函数和方法的回调使用
- 为php闭包附加并封装状态
- 使用use关键字
- 使用bindTo()方法附加闭包的状态
- Zend OPcache 字节码缓存
- php 内置的 http服务器
- php路由脚本(作用和apache及nginx 中的 .htaccess 文件一样)
- 利用 php_sapi_name() 函数查明使用的是哪个php web 服务器,如果当前脚本由php内置的服务器伺服,这个函数会返回字符串 cli-server
标准
- php框架的互操作性(通过接口、自动加载机制和标准的风格让框架相互合作)
- 自动加载:自动加载指,php解释器在运行时按需自动找到并加载php类的过程 (之前php组件和框架会使用__autoload() 或最新的 spl_autoload_register()方法实现各自特有的自动加载器)
- PSR (PHP Standards Recommendation)
- PSR-1 :基本的代码风格
- php标签
必须把php代码放在或 标签中 - 编码
所有的php文件都必须使用UTF-8字符集编码,且不能有字节顺序标记 - 目的
一个php文件可以定义符号(类、性状、函数和常量等),或者执行有副作用的操作(例:生成结果或处理数据),但不能同时做这两件事。 - 自动记载
php命名空间和类必须遵守PSR-4自动加载器标准。我们只需为php符号选择合适的名称并把定义符号的文件放在预期的位置 - 类的名称
使用驼峰式。如:CoffeeGrinder - 常量的名称
必须全部使用大写字母,如果有需要可以使用下划线把单词分开 - 方法的名称
方法名的首字母是小写的,后续单词的首字母是大写的,例:phpIsAwesome
- php标签
- PSR-2 :严格的代码风格
- 缩进
建议使用4个空格缩进 - 文件和代码行
php文件必须使用UNIX风格的换行符,最后要有一个空行,且不能使用php关闭标签,每行代码不超过80个字符,至多不能超过120个字符,每行末尾不能有空格 - 关键字
php关键字比如:true,false,null 等关键字使用小写字母形式 - 命名空间
每个命名空间声明语句后必须跟一个空行,使用use关键字导入命名空间或为命名空间创建别名时,在一系列use声明语句后要加一个空行 - 类
类定义体的起始括号应该在类名之后新起一行写起始括号,类定义体的结束括号必须在定义体之后新起一行写,如果类扩展其他类或实现接口,extends和implements关键字必须和类名写在同一行 - 方法
方法定义体的括号和类定义体的括号位置一样,方法的起始圆括号之后没有空格,结束圆括号之前也没有空格,方法的每个参数(除最后一个)后面有一个逗号和空格 - 可见性
类中的每个属性和方法都要声明可见性,可见性由public、protected或private指定,其作用决定内部和外部如何访问属性和方法。如果把类属性或方法声明成abstract或final,这两个限定符必须放在可见性关键字之前,static 必须放在可见性关键字之后 - 控制结构
控制结构关键字后面要有一个空格,如果控制结构关键字后面有一对括号,起始圆括号后面不能有空格,结束圆括号之前不能有空格;与类和方法的定义体不同,控制结构关键字后面的其起始括号应该和控制结构关键字写在同一行,控制结构关键字后面的结束括号必须单独写在一行
- 缩进
- PSR-3 日志记录器接口
Monolog组件完全实现了PSR-3接口,而且便于使用自定义的消息格式化程序和处理程序扩展功能 - PSR-4 自动加载器
自动加载器策略是指:在运行时按需查找php类、接口或性状,并将其载入php解释器
一般不自己写自动加载器,使用composer 自动生成的PSR-4自动加载器
- PSR-1 :基本的代码风格
组件
- 组件是打包的代码,用于帮你解决php应用中某个具体的问题
- 好的php组件特征
- 作用单一
- 小型
- 合作,组件就是为了和其他组件合作,组件会把代码放在自己的命名空间中,防止与其他组件有名称冲突
- 测试良好
- 文档完善
- 建议:最流行框架有:
- Aura
- Laravel
- Symfony
- Yii
- Zend
- 查找组件
- 在Packagist(https://packagist.org)查找现代php组件
- Awesome PHP (https://github.com/ziadoz/awesome-php)
- 使用php组件
使用composer安装组件 要将composer.json 和 composer.lock文件 纳入版本控制 - 自动加载php组件
composer 下载php组件时还为项目的所有依赖创建一个符合PSR标准的自动加载器,需要在入口文件或者php文件的顶部引入即可 - 命名空间
组件的命名空间不一定与组件的厂商名和包名一致(组件使用的命名空间与组件的厂商名和包名无关)。厂商名和包名只是为了让Packagist和composer识别组件,而组件的命名空间是为了在php代码中使用组件 - 文件系统的组织方式
php组件的文件系统结构基本上是一定的- src
- tests
- composer.json 必须是有效的json
- name
- description
- keywords
- homepage
- license
- authors
- support
- require
- require-dev
- suggest
- autoload
- README.md
- 组件的名称和描述
- 安装说明
- 用法说明
- 测试说明
- 贡献方式说明
- 支持资源
- 作者信息
- 软件许可证
- CONTRIBUTING.md
- LICENSE
- CHANGELOG.md
- 实现组件,版本控制,提交到packagist并使用组件
良好实践
- 过滤、验证和转义
过滤输入、验证数据、转义输出-
过滤输入
转义或删除不安全的字符,在数据到达应用的存储层之前,一定要过滤输入数据,最需要过滤的输入数据类型有:HTML、sql查询和用户资料- 过滤html要使用htmlentities()函数,默认情况下这个函数不会转义单引号,而且也不会检测出输入字符串的字符集。该函数的正确使用方法:
第一个参数是输入字符串
第二个参数是ENT_QUOTES常量,转义单引号
第三个参数设为输入字符串的字符集
如果需要更多过滤html输入方式,可以使用html Purifier库,缺点:速度慢,而且可能难以配置
不要使用正则表达式过滤html,正则表达式很复杂吗,可能导致html无效且出错的几率高
2. sql查询
在sql查询中一定不能使用未过滤的输入数据。如果需要在sql查询中使用输入数据,要使用pdo预处理语句。
3. 用户资料信息
php filter_var() 和 filter_input() 函数的参数能使用不同的标志,过滤不同的类型的输入:电子邮件地址、url编码字符串、整数、浮点数、HTML字符、url和特定范围内的ASCII字符 - 过滤html要使用htmlentities()函数,默认情况下这个函数不会转义单引号,而且也不会检测出输入字符串的字符集。该函数的正确使用方法:
-
验证数据
验证是为了保证在应用的存储层保存符合特定格式的正确数据。如果遇到无效数据要终止数据存储操作,并显示适当的错误消息来提醒应用的用户
可以吧某个FILTER_VALIDATE_* 标志传给filter_var()函数验证用户的输入
如果验证成功返回的是要验证的值,如果验证失败返回值是false
推荐验证功能的组件- aura/filter
- respect/validation
- symfony/validator
建议:输入数据既要验证也要过滤,以此确保输入数据时安全的,而且符合预期
-
转义输出
把输入渲染成网页或API响应时,一定要转义输出。
可以使用htmlentities()函数转义输出。第二个参数一定要使用ENT_QUOTES,这个函数转义单引号和双引号。而且,还要在第三个参数中指定合适的字符编码(通常是UTF-8) -
密码
- 绝对不能知道用户的密码
- 绝对不要约束用户的密码
- 绝对不能通过电子邮件发送用户的密码
- 使用bcrypt计算用户密码的哈希值
- 验证密码 使用password_verify()函数
- 在登录之前一定要检查用户记录中现有的密码哈希值是否过期,如果过期了需要重新计算密码的hash值
password_needs_rehash() 函数检查用户记录中现有的密码的哈希值是否需要更新 - php 5.5.0之前的密码哈希API
如果无法使用php5.5.0或以上版本,可以使用 ircmaxell/password-compat组件
-
日期、时间和时区
使用DateTime、DateInterval和DateTimeZone类- 设置默认时区
- Date Time 类
- DateInterval类
- DateTimeZone类
- DatePeriod类 时间迭代器
- nesbot/carbon组件 处理日期和时间值
-
数据库
- PDO扩展
PDO实例的作用是把php和数据库连接起来 - 数据库连接和DSN
- PDO预处理语句及pdo中使用数据库的事务
- 多字节字符串 使用 mbstring扩展 否则可能会损坏多字节Unicode数据
- 处理多字节时要注意:
- 一定要知道数据的字符编码
- 使用utf-8字符编码存储数据
- 使用utf-8字符编码输出数据
mb_detect_encoding() 和 mb_convert_encoding() 函数将一种字符编码转换成另一种字符编码
- 输出UTF-8数据
在php文件的最上方使用header函数
在html文档的头部加入 meta标签
- PDO扩展
-
流
1.
在出发地和目的地之间传输数据
1. file_get_contents()
2. fopen()
3. fwrite()
4. fclose()
2. 流封装协议
3. 流上下文
4. 流过滤器
stream_filter_append()函数 -
错误和异常
- @ 可以忽略错误,但是不建议这样做
- 关于报告错误的方式要满足以下几点:
- 一定要让php报告错误
- 在开发环境中要显示错误
- 在生产环境中不能显示错误
- 在开发环境和生产环境中都要记录错误
- whoopse组件 在开发环境中显示错误和异常
- monolog 组件 在生产环境中 记录日志
-
主机
nginx的配置
深入理解PHP之:Nginx 与 FPM 的工作机制
- CGI和FastCGI协议
- nginx 接收到请求后将请求转发给fpm fpm处理后再返回到nginx 再返回给浏览器
调优
- 内存
- php.ini 文件中的memory_limit选项设定单个php进程可以使用的系统内存最大值
- 可以使用Apache Bench 或 Seige 工具在类似生产环境的条件下对php应用做压力测试
- Zend OPcache
- 文件上传
- 最长执行时间
- 处理会话 将php会话存储在memcache或者redis中
- 缓冲输出
如果在较小的块中发送更多的数据,而不是在较多的块中发送较少的数据,那么网络的效率会更高 - 真实路径缓存
部署
- Capistrano 自动部署应用的软件
测试
- 单元测试 phpunit测试
- 自动测试 Travis CI测试服务
分析
- 基准测试工具 apache bench 和 siege 可以找出性能问题
- 分析器
- Xdebug 只在开发环境中使用 需要借助KCacheGrind 和 WinCacheGrind 显示分析的结果
- XHProf 可以在开发和生产环境中使用 需要借助XHGUI显示分析结果
- New Relic 适合在开发环境中使用
- Blackfire
HHVM和Hack
- 使用Supervisord 监控 HHVM
- HHVM运行的FastCGI服务器的作用和php-fpm的完全一样
- HHVM 、 FastCGI 和 Nginx
- HHVM 通过 FastCGI协议与web服务器(例:nginx)通信
- 创建一个nginx虚拟主机,将php请求转发给hhvm的FastCGI服务器
- Hack语言
- 类型
- 静态类型和动态类型的之间的主要区别在于何时检查程序中的类型,以及如何测试程序使用的类型是否正确
- 静态语言通常都需要编译
- 在运行时才会检查程序中的类型
- hack的模式
- strict 严格模式
- partial 局部模式
- decl 声明模式