PHP 边边角角
2020-02-09 PHP
Ubuntu 快速安装 PHP
PHP 7.2
sudo add-apt-repository ppa:ondrej/php && sudo apt-get update
# 稳定版本
sudo apt-get -y install php7.2
# 开发版:
# sudo apt-get -y install php7.2-dev
sudo apt-get install -y php7.2-fpm php7.2-mysql php7.2-curl php7.2-json php7.2-mbstring php7.2-xml php7.2-intl
sudo apt-get install openssl
sudo apt-get install php7.2-gd -y &&
sudo apt-get install php7.2-soap -y &&
sudo apt-get install php7.2-gmp -y &&
sudo apt-get install php7.2-odbc -y &&
sudo apt-get install php7.2-pspell -y &&
sudo apt-get install php7.2-bcmath -y &&
sudo apt-get install php7.2-enchant -y &&
sudo apt-get install php7.2-imap -y &&
sudo apt-get install php7.2-ldap -y &&
sudo apt-get install php7.2-opcache -y &&
sudo apt-get install php7.2-readline -y &&
sudo apt-get install php7.2-sqlite3 -y &&
sudo apt-get install php7.2-xmlrpc -y &&
sudo apt-get install php7.2-bz2 -y &&
sudo apt-get install php7.2-interbase -y &&
sudo apt-get install php7.2-pgsql -y &&
sudo apt-get install php7.2-recode -y &&
sudo apt-get install php7.2-sybase -y &&
sudo apt-get install php7.2-xsl -y &&
sudo apt-get install php7.2-cgi -y &&
sudo apt-get install php7.2-dba -y &&
sudo apt-get install php7.2-phpdbg -y &&
sudo apt-get install php7.2-snmp -y &&
sudo apt-get install php7.2-tidy -y &&
sudo apt-get install php7.2-redis -y &&
sudo apt-get install php7.2-memcache -y &&
sudo apt install php7.2-xdebug -y &&
sudo apt-get install php7.2-zip -y
PHP 7.4
sudo add-apt-repository ppa:ondrej/php && sudo apt-get update
sudo apt-get -y install php7.4
sudo apt-get install -y php7.4-fpm php7.4-mysql php7.4-curl php7.4-json php7.4-mbstring php7.4-xml php7.4-intl
sudo apt-get install openssl
sudo apt-get install php7.4-gd -y &&
sudo apt-get install php7.4-soap -y &&
sudo apt-get install php7.4-gmp -y &&
sudo apt-get install php7.4-odbc -y &&
sudo apt-get install php7.4-pspell -y &&
sudo apt-get install php7.4-bcmath -y &&
sudo apt-get install php7.4-enchant -y &&
sudo apt-get install php7.4-imap -y &&
sudo apt-get install php7.4-ldap -y &&
sudo apt-get install php7.4-opcache -y &&
sudo apt-get install php7.4-readline -y &&
sudo apt-get install php7.4-sqlite3 -y &&
sudo apt-get install php7.4-xmlrpc -y &&
sudo apt-get install php7.4-bz2 -y &&
sudo apt-get install php7.4-interbase -y &&
sudo apt-get install php7.4-pgsql -y &&
sudo apt-get install php7.4-recode -y &&
sudo apt-get install php7.4-sybase -y &&
sudo apt-get install php7.4-xsl -y &&
sudo apt-get install php7.4-cgi -y &&
sudo apt-get install php7.4-dba -y &&
sudo apt-get install php7.4-phpdbg -y &&
sudo apt-get install php7.4-snmp -y &&
sudo apt-get install php7.4-tidy -y &&
sudo apt-get install php7.4-redis -y &&
sudo apt-get install php7.4-memcache -y &&
sudo apt install php7.4-xdebug -y &&
sudo apt-get install php7.4-zip -y
PHP 优点
- 完善的面向对象编程支持,主要包括
- namespace 处理命名冲突
- interface 分离实现与接口
- traits 代码混入(mixin)支持
- 类型系统 限制函数参数、返回值、类成员的类型
- 完善的依赖管理体系,这一点主要由 composer 实现
- 支持 FFI(foreign function interface),可以很方便的跟各种C语言库(如 TensorFlow)交互,极大地扩展了 PHP 的能力
- 更加安全,主要是引入了更加现代更加安全的密码学类库 libsodium
- 性能不断提升,PHP7.4 的性能大约是 PHP5.6 的 3 倍,比 PHP7.0 也快了近 18%, 主要的性能提升来自于 PHP7.0 的 zval 重构,而 PHP7.4 也能过引入 preload 特性进一步加快了代码的执行速度,PHP8.0 将引入 JIT 技术,性能会有更大的提升
PHP 不足
- 不支持泛型。程序员无法限制PHP的数组的成员类型。
- 运行时类型检查。PHP的参数类型检查是在代码执行的过程完成的,降低了执行效率。
- 不支持多核。PHP虚拟机就是一个C语言的 while 循环,边读取边执行。如果想跑满多核,只能利用多进程或都多线程,多线程存在同步问题,多进程存在IPC问题。
- PHP本身和扩展都使用C语言开发,要想深入理解PHP,单写PHP代码是不够的。这在一定程度上增加了改进PHP的门槛。
- 性能相比编译语言依然差很远
- 生态
PHP7 比 PHP5 性能提升在哪里
1、变量存储字节减小,减少内存占用,提升变量操作速度 2、改善数组结构,数组元素和 hash 映射表被分配在同一块内存里,降低了内存占用、提升了 cpu 缓存命中率 3、改进了函数的调用机制,通过优化参数传递的环节,减少了一些指令,提高执行效率
生命周期
- 模块初始化阶段 (Module init):即调用每个拓展源码中的的 PHP_MINIT_FUNCTION 中的方法初始化模块,进行一些模块所需变量的申请,内存分配等
- 请求初始化阶段 (Request init):即接受到客户端的请求后调用每个拓展的 PHP_RINIT_FUNCTION 中的方法,初始化 PHP 脚本的执行环境
- 执行该 PHP 脚本
- 请求结束 (Request Shutdown):这时候调用每个拓展的 PHP_RSHUTDOWN_FUNCTION 方法清理请求现场,并且 Zend Engine 开始回收变量和内存
- 关闭模块 (Module shutdown):Web 服务器退出或者命令行脚本执行完毕退出会调用拓展源码中的 PHP_MSHUTDOWN_FUNCTION 方法
主流框架请求声明周期
- 用户向入口脚本
index.php
发起请求 - 入口脚本加载应用配置并创建一个应用实例去处理请求
- 应用通过请求组件解析请求的路由
- 应用创建一个控制器实例去处理请求
- 控制器创建一个动作实例并针对操作执行过滤器
- 如果任何一个过滤器返回失败,则动作取消
- 如果所有过滤器都通过,动作将被执行
- 动作会加载一个数据模型,或许是来自数据库
- 动作会渲染一个视图,把数据模型提供给它
- 渲染结果返回给响应组件
- 响应组件发送渲染结果给用户浏览器
php://input 是什么
php://input
是个只读流,用于获取请求体,返回整个 HTTP 请求中,除去 HTTP 头部的全部原始内容,而不管是什么 Content Type(或称为编码方式)。
相比较之下,$_POST 只支持 application/x-www-form-urlencoded 和 multipart/form-data-encoded 两种 Content Type。
其中前一种就是简单的 HTML 表单以 method=“post” 提交时的形式,后一种主要是用于上传文档。因此,对于诸如 application/json 等 Content Type,
这往往是在 AJAX 场景下使用,那么使用 $_POST 得到的是空的内容,这时就必须使用 php://input。
相比较于 $HTTP_RAW_POST_DATA ,php://input 无需额外地在 php.ini 中激活 always-populateraw-post-data ,而且对于内存的压力也比较小, 当编码方式为 multipart/form-data-encoded 时,php://input 是无效的。这种情况一般为上传文档。这 种情况可以使用传统的 $_FILES 或者 Yii 框架中的 yii\web\UploadedFile。
获取请求头
- getallheaders(),该方法仅在将 PHP 作为 Apache 的一个模块运行时有效
- http_get_request_headers(), 该方法要求 PHP 启用 HTTP 扩展
- $SERVER 数组的方法,需要遍历整个数组,并将所有以 HTTP* 元素加入到集合中去。并且要将所有 HTTP_HEADER_NAME 转换成 Header-Name 的形式,根据不同的 PHP 环境采用有效的方法来获取请求头部
502 报错
问题原因分析:502 bade gateway 一般都是 upstream 出错,对于 PHP,造成 502 的原因常见的就是脚本执行超过 timeout 设置时间或者 timeout 设置过大,导致 PHP 进程长时间不能释放。
控制 PHP 脚本执行时间的配置有两种:
- php.ini 文件中 max_execution_time (全局配置)
- php-fpm.conf 中 request_terminate_timeout
如何解决
- 适当增大 php 脚本执行时间,通过修改 php.ini 或 php-fpm.conf 来配置
- 从根本原因出发,定位 php 脚本, 查出真正导致 php 执行时间过长的原因 (例如 循环嵌套过多,数据库死锁)
- 高并发的话考虑 php-fpm.conf 中的 max_children 最大子进程数
- 是否启动 php-fpm
请手动释放你的资源
安全配置
- error_reporting 设置为 Off:不要暴露错误信息给用户,开发的时候可以设置为 ON
- safe_mode 设置为 Off
- register_globals 设置为 Off
- 禁用以下函数:system、exec、passthru、shell_exec、proc_open、popen
- open_basedir 设置为 /tmp, 这样可以让 session 信息有存储权限,同时设置单独的网站根目录
- expose_php 设置为 Off
- allow_url_fopen 设置为 Off
- allow_url_include 设置为 Off
监听方式
Nginx 中的 fastcgi_pass 为什么有时候是 unix:/tmp/php-fpm.sock
,有时候是 127.0.0.1:9000
?
UNIX Domain Socket 是一种 IPC 机制,它不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,而是直接将应用层数据从一个进程拷贝到另一个进程。
两种方式的区别在于:
- UNIX Domain Socket 适用于 PHP 和 Nginx 在同一服务器,不经过协议层和网卡,可以避免数据传输经过 TCP 层造成导致 TIME_WAIT 连接过多的问题
- IP 地址 两种模式都支持 (无论 Nginx 和 PHP 是否位于同一服务器)
# IP 地址方式:
php-fpm.conf: listen = 127.0.0.1:9000;
nginx.conf: fastcgi_pass 127.0.0.1:9000;
# UNIX Domain Socket 方式:
php-fpm.conf: listen = /tmp/php-fpm.socknginx.conf;
nginx.conf: fastcgi_pass unix:/tmp/php-fpm.sock;
长连接方案
虽然能实现,但是无法克服 PHP 的先天性缺陷,导致请求和响应对应容易出问题。
每个语言都有适用的场景,PHP 目前依旧适用的场景就是管理后台 API + 中小系统 + 大型系统中需要快速迭代并验证的模块功能。