来自 金沙js77888 2020-01-31 20:23 的文章
当前位置: 金沙js77888 > 金沙js77888 > 正文

从框架的封闭生态中走出来

系列笔记:Modern PHP 笔记:语言特性Modern PHP 笔记:良好实践Modern PHP 笔记:部署测试和调优

相比于上一篇笔记Modern PHP 笔记:语言特性,第二部分侧重讲标准和良好实践,更加实战。

PHP-FIG(PHP Framework Interop Group)2009年

通过接口、自动加载、代码风格,使框架相互合作

PSR: PHP Standard Recommendation

  • PSR-1: 基础编码规范
  • PSR-2: 编码风格规范
  • PSR-3: 日志接口规范
  • PSR-4: 自动加载规范
  • PSR-6: 缓存接口规范
  • PSR-7: HTTP 消息接口规范

可以看点击链接看详细的中文版。很多方案在起草中,也有废弃的,比如PSR-4就是替代PSR-0的

多用组件,从框架的封闭生态中走出来,减少重复造轮子。

打包的代码,一系列相关的类、接口、性状

框架的问题是:需要更多投入,框架提供很多工具,但是可能缺少我们需要的。把第三方代码集成上去费时费力。框架本身的维护也需要很多人力。

使用正确的工具做正确的事

  • 如果是一些PHP组件就能搞定的小项目,用组件。
  • 多个团队成员开发,用框架。它能提供约定、准则、结构等,加速开发。

组件库Packagist

优秀组件可参考Awesome PHP:

使用composer下载并自动加载依赖组件

使用composer

composer require vendor/package

composer.lock文件会列出使用的所有组件和具体版本号,确保组件版本一致。

composer install // 不会更新.lockcomposer update // 更新.lock到最新版

自动加载

只需要一句,不用一一引入

require 'vendor/autoload.php'

composer和私有仓库

不方便开源的组件也可以使用composer

  1. 取一个厂商名和包名

  2. 定一个命名空间

  3. 文件系统

     src/ 源码 tests/ 测试 composer.json composer的配置文件,描述组件、依赖等 README.md CONTRIBUTING.md 说明如何为这个组件做贡献 LISENSE 组件许可证 CHANGELOG.md 每个版本引入的改动
    
  4. composer.json

     require 列出需要的最小依赖 require-dev 列出开发组件需要的依赖
    
  5. 实现组件

  6. 发到版本控制

  7. 提交到 Packagist

  8. 使用组件 composer require

不要相信任何人。

包括:

  • $_GET
  • $_POST
  • $_REQUEST
  • $_COOKIE
  • $argv
  • php://stdin
  • php://input
  • file_get_contents()
  • 远程数据库
  • 远程API
  • 来自客户端的数据

过滤输入

转义或删除不安全的字符。

使用htmlentities()函数,但是它默认不会转义单引号,正确使用方式:第一个参数是输入字符串,第二额参数设为ENT_QUOTES常量,转义单引号,第三个参数设为输入字符串的字符集。

$htmlentities($input, ENT_QUOTES, 'UTF-8');

如果需要更多过滤HTML方式,可以使用HTML Purifier库。

使用PDO预处理语句

filter_var()filter_input()函数

  • 过滤电子邮件 filter_var($email, FILTER_SANITIZE_EMAIL);

  • 过滤用户资料中的外国字, 删除小于ASCII 32的字符,转义大于ASCII 127的字符

     filter_var( $string, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW|FILTER_FLAG_ENCODE_HIGH);
    

验证数据

区别于过滤数据会删除,验证不会,只是确保符合特定格式。传递FILTER_VALIDATE_*标志给filter_var()函数。验证失败返回false,否则返回原值。

 //验证电子邮件 $input = 'john@example.com' $isEmail = filter_var($input, FILTER_VALIDATE_EMAIL); if ($isEmail !== false) { echo 'success'; } else { echo "fail"; }

推荐组件:

  • aura/filter
  • respect/validation
  • symsony/validator

转义输出

很多模板引擎(e.g., twig、smarty)会自动转义,否则使用htmlentities($output, ENT_QUOTES, 'UTF-8');

  • 绝对不能知道用户的密码
  • 绝对不能约束用户的密码
  • 绝对不能通过电子邮件发送用户的密码

使用bcrypt计算用户密码的哈希值

应该用哈希,而不是加密。加密是双向算法,可以解密,而哈希是单向算法。哈希算法很多,一般用bcrypt,与MD5和SHA1不同,bcrypt故意设计的很慢,多次处理数据。

密码哈希API

 // 验证电子邮件 // 验证密码 // 创建密码哈希值 // 创建用户账户 // 重定向登录账户

 // 从请求主体获取电子邮件地址 // 从请求主体获取密码 // 使用电子邮件查询账户 password_verify(); // 验证密码和账户哈希值是否匹配 password_needs_rehash(); // 如果需要,重新计算哈希值 // 把登录状态保存在会话中 // 重定向到个人资料页

PHP5.5.0之前,使用组件ircmaxell/password-compat

设置默认时区

// php.inidate.timezone = 'America/New_York';// *.phpdate_default_timezone_set('America/New_York');

DateTime类

构造$datetime = new DateTime('2014-09-08 5:03 AM');自定义格式DateTime::createFromFormat('M j, Y H:i:s', 'Jan 2, 2014 23:09:12')

DateInterval类

表示固定的时间段,DateInterval用于修改DateTime实例.

 $datetime = new DateTime('2014-09-08 5:03 AM'); $interval = new DateInterval; $datetime->add($interval); echo $datetime->format('Y-m-d H:i:s');

DateTimeZone类

 $timezone = new DateTimeZone('America/New_York'); $datetime = new DateTime('2014-09-08 5:03 AM', $timezone);

DatePeriod类

一段时期内反复出现的一系列日期和时间

 $period = new DatePeriod($startDateTime, $interval, 3);

nesbot/carbon组件

PDO扩展,PHP Data Objects,PHP数据对象,是一系列类,抽象了不同数据库的具体实现。

这里实际上现在框架的ORM用的很好,不需要直接PDO了。

 // 预处理语句 $sql = 'select id from user where email = :email'; $statement = $pdo->prepare; $email = filter_input(INPUT_GET, 'email'); $statement->bindValue(':email', $email); // ':email'是占位符 // 查询结果 $statement->execute(); // 迭代结果 while (($result = $statement->fetch(PDO::FETCH_ASSOC)) !== false) { echo $result['email']; }

事务

 $pdo->beginTransaction(); // sql $pdo->commit();

使用mbstring扩展,比如用mb_strlen()代替原生的strlen()

处理字符编码:

  • 一定要知道数据的字符编码

  • 使用utf-8存储数据

  • 使用utf-8输出数据

     // php.ini default_charset = 'UTF-8';
    

流的作用是在出发地和目的地之间传输数据。出发地和目的地可以是文件、命令行进程、网络连接、ZIP或TAR压缩文件、临时内存、标准输入和输出、或者是PHP流封装协议实现的其他资源。就是管道

流封装协议

流协议和目标格式:

 <scheme>://<target>

下面例子里file_get_contents()的字符串参数是流标识符,只是因为HTTP流协议就是这样,像URL

 $json = file_get_contents( 'http://api.flickr.com....' )

还有其他file://流封装协议、php://流封装协议

流上下文

有些流接受的可选参数,成为流上下文使用stream_context_creat()函数创建

流过滤器

流真正的强大之处:过滤、转换、添加、删除流中传输的数据。有string.toupper等,大多需要自定义stream_filter_append()

自定义流过滤器

自定义流过滤器是个PHP类,扩展内置的php_user_filter类,实现一些方法,然后用stream_filter_register()注册。

错误会导致脚本停止,异常时PHP错误处理面向对象的产物,异常要先实例化,然后抛出,最后再捕获。

异常

异常是Exception类的对象。$exception = new Exception('msg', -1);抛出异常throw new Exception('msg', -1);,异常抛出后程序会终止。捕获异常try {...} catch { }

异常处理程序

设置一个全局异常处理程序,捕获所有未捕获的异常。

 set_exception_handler(function (Exception $e) { // 处理并记录异常 }); // 编写其他代码 // 还原之前的异常处理程序 restore_exception_handler();

错误

在开发环境,显示并记录所有错误信息;

在生产环境,记录大多数错误信息,但不显示出来;

 set_error_handler(); // 全局错误处理程序 restore_error_handler();

在开发环境中处理错误和异常

使用Whoops组件

在生产环境处理错误和异常

使用Monolog组件

本文由金沙js77888发布于金沙js77888,转载请注明出处:从框架的封闭生态中走出来

关键词: php 笔记 Modern