PHP开发进阶:20个实用性能优化技巧与最佳实践

在Web开发领域,性能优化始终是PHP开发者永恒的话题。随着用户对响应速度的要求越来越高,如何让PHP应用跑得更快、更稳,成为了衡量开发者水平的重要标准。本文将结合最新的PHP 8.x特性和行业最佳实践,为你分享20个立竿见影的性能优化技巧。

环境优化:从根源提升性能. 升级到最新PH版本这是最简单也最有效的优化手段。PHP 7系5列性能提升了2-3倍,而PHP 8.x又在7的基础上带来了显著提升,尤其是JIT编译器的引入。仅仅升PHP版本,就能让你的应性能直接翻倍。
. 启用并合理配置OPcacheOPcache是PHP性能优化的基石,它能将编译后的字节码存到内存中,避免每次请求都重新解析和编译脚本。opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=4000
opcache.validate_timestamps=0  # 生产环境建议关闭
opcache.revalidate_freq=60      # 开发环境可设置
files=4000
opcache.validate_timestamps=0  # 生产环境建议关闭
opcache.revalidate_freq=60      # 开发环境可设置
```
### 3. 优化Composer自动加载
使用`composer dump-autoload --optimize`或`--classmap-authoritative`参数生成优化的自动加载器,减少文件查找开销。

## 二、数据库优化:解决性能瓶颈的核心

### 4. 避免N+1查询问题
这是最常见的性能杀手之一。在循环中执行数据库查询会导致大量重复请求,应使用JOIN语句或批量查询替代。

**错误示例:**
```php
// 循环中查询每个用户的详情
foreach ($userIds as $id) {
    $user = $db->query("SELECT * FROM users WHERE id = $id");
}
```

**优化方案:**
```php
// 批量查询所有用户
$users = $db->query("SELECT * FROM users WHERE id IN (" . implode(',', $userIds) . ")");
```

### 5. 合理使用索引
确保关键字段(WHERE、JOIN、ORDER BY中使用的字段)都有合适的索引。使用`EXPLAIN`命令分析查询计划,避免全表扫描。

### 6. 避免SELECT *,只查询需要的字段
查询不需要的字段会增加数据传输和内存消耗,显著影响性能。

**优化前:**
```php
$result = $db->query("SELECT * FROM users WHERE id = 1");
```

**优化后:**
```php
$result = $db->query("SELECT id, name, email FROM users WHERE id = 1");
```

### 7. 使用预处理语句
预处理语句不仅能防止SQL注入,还能让数据库重复执行相同的查询计划,提升执行效率。

```php
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);
$user = $stmt->fetch();
```

### 8. 合理使用缓存
对于不经常变动但访问频繁的数据(如配置信息、热门文章),使用Redis或Memcached缓存,减轻数据库压力。

```php
// 使用APCu缓存单条记录
$user = apcu_fetch("user_123");
if (!$user) {
    $user = $db->query("SELECT * FROM users WHERE id = 123")->fetch();
    apcu_store("user_123", $user, 3600); // 缓存1小时
}
```

## 三、代码逻辑优化:编写高效的PHP代码

### 9. 优化循环结构
避免在循环内部执行重复计算和耗时操作,将不变的计算移出循环体。

**错误示例:**
```php
for ($i = 0; $i < count($array); $i++) {
    // 每次循环都调用count(),O(n²)复杂度
}
```

**优化后:**
```php
$count = count($array);
for ($i = 0; $i < $count; $i++) {
    // 只计算一次数组长度
}
```

### 10. 优先使用foreach遍历数组
foreach底层直接操作哈希表指针,比for+count()的组合更快更安全,尤其适合遍历大型数组。

### 11. 减少函数调用开销
避免在循环中频繁调用函数,将函数调用结果缓存到变量中。优先使用PHP内置函数,它们通常比自定义函数更快。

### 12. 合理使用数据类型
PHP是弱类型语言,但合理使用数据类型能提升性能。例如,使用索引数组而非关联数组进行遍历,使用整数而非字符串作为数组键。

### 13. 及时释放内存
对于大型数组或对象,不再使用时及时用`unset()`释放内存,尤其是在循环中反复创建大对象的场景。

```php
unset($largeArray); // 释放大数组占用的内存
```

### 14. 使用生成器处理大数据集
生成器(yield)允许你按需生成数据,而不是一次性加载到内存中,特别适合处理大文件或大数据量查询。

```php
function getLargeFileLines($filePath) {
    $file = fopen($filePath, 'r');
    while (($line = fgets($file)) !== false) {
        yield $line;
    }
    fclose($file);
}

// 逐行处理,内存占用极低
foreach (getLargeFileLines('large_file.txt') as $line) {
    processLine($line);
}
```

## 四、输出与资源优化

### 15. 开启Gzip压缩
通过配置Web服务器(Nginx/Apache)开启Gzip压缩,减少HTML、CSS、JS等静态资源的传输体积。

### 16. 优化静态资源
将CSS和JS文件合并压缩,使用CDN加速静态资源访问,设置合理的缓存策略。

### 17. 禁用output_buffering处理大文件
当处理大文件上传或下载时,禁用output_bob_end_clean(); // 关闭输出缓冲uffering,避免内存溢出。

`rob_end_clean(); // 关闭输出缓冲eadfile('larob_end_clean(); // 关闭输出缓冲ob_end_clean(); // 关闭输出缓冲
readfile('large_file.zip'); // 直接输出文件内容ge_file.zi## 五、高级readfile('large_file.zip'); // 直接输出文件内容优化技巧p'); // 直接输readfile('large_file.zip'); // 直接输出文件内容出文件内容
``## 五、高级优化技巧
### 18. 使用异步处理## 五、高级优化技巧
将耗时任务(如发送邮件、生成报表)放入消息队列(如RabbitMQ、Redis Queue),异步执行,避免阻塞主请求。

### 19. 利用PHP 8特性
PHP 8带来了许多性能提升特性,如JIT编译器、联合类型、属性注解等,充分利用这些新特性可以让你的代码更高效。

### 20. 性能监控与分析
使用Xdebug、Blackfire等工具进行性能分析,定位性能瓶颈,有针对性地进行优化。

## 总结

性能优化是一个持续的过程,没有银弹。通过以上20个优化技巧,你可以从基础环境、数据库、代码逻辑、资源输出等多个层面全面提升PHP应用的性能。记住,优化的核心是用更少的资源完成更多的工作,在用户体验和服务器成本之间找到最佳平衡。
MiniMax 跨年福利来袭!邀好友享 Coding Plan 双重好礼,助力开发体验!
好友立享 9折 专属优惠 + Builder 权益,你赢返利 + 社区特权!
立即参与:https://platform.minimaxi.com/subscribe/coding-plan?code=3D4KQ3e5cl&source=link
在ubuntu上使用pdftopng可能会出现如下错误:
Config Error: No display font for 'Symbol'
Config Error: No display font for 'Courier'
Config Error: No display font for 'Courier-Bold'
Config Error: No display font for 'Courier-BoldOblique'
Config Error: No display font for 'Courier-Oblique'
Config Error: No display font for 'Helvetica'
Config Error: No display font for 'Helvetica-Bold'
Config Error: No display font for 'Helvetica-BoldOblique'
Config Error: No display font for 'Helvetica-Oblique'
Config Error: No display font for 'Times-Bold'
Config Error: No display font for 'Times-BoldItalic'
Config Error: No display font for 'Times-Italic'
Config Error: No display font for 'Times-Roman'
Config Error: No display font for 'ZapfDingbats'
解决方案就是添加相应的字体即可, Symbol和 ZapfDingbats 字体可以在下面的链接进行下载
http://www.xpdfreader.com/download.html  
下载后,解压上传到服务器任意位置,然后使用
vi ~/.xpdfrc
添加如下内容,注意将字体路径修改为你实际上传的路径
fontFile        Symbol  /usr/local/share/xpdf/xpdf-t1fonts/s050000l.pfb
fontFile        ZapfDingbats    /usr/local/share/xpdf/xpdf-t1fonts/d050000l.pfb

其他字体可以在网上下载后通过同样的方式添加
fontFile        Courier /usr/share/fonts/Courier.ttf
fontFile        Courier-Bold /usr/share/fonts/Courier.ttf
fontFile        Courier-BoldOblique     /usr/share/fonts/Courier.ttf
fontFile        Courier-Oblique /usr/share/fonts/Courier.ttf
fontFile        Times-Bold      /usr/share/fonts/Courier.ttf
fontFile        Times-BoldItalic        /usr/share/fonts/Courier.ttf
fontFile        Times-Italic    /usr/share/fonts/Courier.ttf
fontFile        Times-Roman     /usr/share/fonts/Courier.ttf
fontFile        Helvetica /usr/share/fonts/Helvetica.ttf
fontFile        Helvetica-BoldOblique   /usr/share/fonts/Helvetica.ttf
fontFile        Helvetica-Oblique       /usr/share/fonts/Helvetica.ttf
fontFile        Helvetica-Bold  /usr/share/fonts/Helvetica-Bold.ttf

小技巧,如果找不到某个字体,可以使用其他相近的字体代替



反向代理配置中增加

RequestHeader set HTTPS on

后端php程序使用

$_SERVER['HTTP_HTTPS'] == 'on' 来判断

郑重提醒:不要轻易参考B站的视频就动手拆解,有几个地方有区别

  1. 键盘的构造不一致,视频中的都是有铁质支架在里面的,新款的是没有的
  2. 有铁质的是从下方撬,新款的应该从上方撬
  3. 新款的有防尘膜,一般人拆解都会废掉防尘膜
附几张杯具的图片
点击查看原图点击查看原图点击查看原图

2022-2-13 16:11 Sunday  
Launching lib/main.dart on HUAWEI MLA AL00 in debug mode...
Could not locate aapt. Please ensure you have the Android buildtools installed.
No application found for TargetPlatform.android_x86.
Is your project missing an android/app/src/main/AndroidManifest.xml?
Consider running "flutter create ." to create one.

解决方案就是 
flutter clean .
2021-10-13 17:52 Wednesday  
在 高版本的android studio 修改包名比较方便,具体流程如下:

进入 Androidmanifest.xml 文件,找到 package 名称,选中需要修改的部分。
比如原包名为
org.phpec.vr
如果需要修改中间的 phpec ,那么我们就选中 phpec,
依次进行 右键 - > Refactor -> Rename,然后选择 Rename package , 或者光标移动到包名上,会出现 Rename to, 点击它。
输入要修改的名称 ,直接点击 Refactor , 左下方继续点击 Do Refactor, 等待修改成功


修改 

uc_server/data/config.inc.php

 

找到

define('UC_FOUNDERPW','xxxxxx');

define('UC_FOUNDERSALT','xxxx');

 

修改为

define('UC_FOUNDERPW','047099adb883dc19616dae0ef2adc5b6');

define('UC_FOUNDERSALT','311254');

 

提示无权限的话修改config.inc.php 文件的权限为可编辑

 

创始人密码就是 123456789 了

 

 

phpstorm中xml不能选择编码打开,同时在设置中针对单文件的设置也无法设置编码,后面我通过一个折中的方法解决了,就是通过在xml文件中右键选择Mark as Plain Text,此时就可以设置文件编码了。
.div1{text-align:center;}
.div1 img{vertical-align:middle;}
.div1:after{content:"";display:inline-block;vertical-align:middle;height:100%;width:0;}
div内容垂直居中左右居中、图片垂直居中左右居中,百分百可行的方案,div也可以。
2020-6-10 23:07 Wednesday  

fluwx微信支付在android上已经正常了,但是在ios上无反应,已经配置了 open.weixin.qq.com 上面的信息,以及配置了info下面的 URL Types

weixin => APPID

点击查看原图

真机调试报 This app is not allowed to query for scheme weixinulapi 这个错误

结果发现是info.plist 缺少下面的内容

<key>LSApplicationQueriesSchemes</key>

<array>

<string>weixin</string>

<string>weixinULAPI</string>

</array>

 

上面的内容之前本来是加上去了,只是后面因为提示隐私权限的问题,当时把这个删除了,结果就出现了上面的问题。

另外说明一下alipay的配置,也是url types 那里,配置  alipay => identifier

昨天晚上遇到笔记本突然不能上网了,手动把wifi关闭打开后一直不正常,有时候还会在wifi状态边上出现 连接状态不明。

 

在2小时内反复尝试多次后,都准备提交apple支持了,突然想到是不是因为我插了一根绿联的扩展坞呢?我买的是type-c转hdmi的,拔掉扩展坞后,网络果然正常了。。

 

看来只能退掉扩展坞了,还好买来没几天,然后想到我来搜一搜,看看别人有同样的问题没,用关键词“mac  绿联 不能上网”果然搜到了有和我同样问题的人,他的文章中就说明了是路由器的2.4G无线应该是和扩展坞的冲突了,建议修改路由器的信道。

 

重新接上扩展坞,修改路由器的信道,然后重启,网络果然正常了。

 

记录一下,我这白瞎的两小时。

 

使用linux下的计划任务做进程守护是比较靠谱的一件事情,因为至少系统的计划任务是不会随便崩掉的。


编写   check.sh (下面的脚本是用于守护某一个docker是否正常运行的,当进程没有守护的时候,使用/opt/ddmysql/start.sh即可以启动)

```

name="ddmysql_web_1"

path="/opt/ddmysql/start.sh"

cd /opt/ddmysql/

server=`docker ps | grep ${name} | grep -v grep`

if [ ! "$server" ]

then

echo "start ${name}...."

t=`date`

echo "${t} ${name}" >> restart_${name}.log

sudo nohup ${path} >/dev/null 2>&1 &

else

echo "runing ${name}..."

fi

```

非docker程序使用 ps aux | grep 关键词 | grep -v grep  检测

start.sh 代码如下 (这个为docker-compose的启动方法,不同的程序有不同的启动方法)

```

docker-compose up -d

```

一般linux下的程序启动使用   

./start.sh

/soft/a/bin 

启动

然后将start.sh 加入到 计划任务中

vi /etc/crontab

```

*/1 * * * * root cd /home/aboc && sh start.sh

```

重新加载计划任务

```

/etc/init.d/cron reload

```

以上脚本只能通过每分钟一次的频率进行检测,如果需要做到不间断的进行检测,我们可以调整一下check.sh这个脚本

```

for a in {0..59};do

server=`docker ps | grep ${name} | grep -v grep`

if [ ! "$server" ]

then

echo "start ${name}...."

t=`date`

echo "${t} ${name}" >> restart_${name}.log

sudo nohup ${path} >/dev/null 2>&1 &

else

echo "runing ${name}..."

fi

sleep 1

done

```

2019-1-25 17:13 Friday  

有时候在做静态网页开发的过程中,需要实时查看页面效果,在不安装iis、Apache或是Nginx的情况下,只能使用file://模式打开,但是很多js功能就不能使用,所以我开发了一个简单的文件目录服务器,支持window和linux,只需要将程序文件放到程序目录下,执行就可以了,程序会自动找到一个可以使用的端口。

 

程序下载地址如下:

https://github.com/abocd/dirweb/releases

 

之所以被屏蔽,是因为里面调用了官方的一个http://www.phpec.org/?tag=%E7%BD%91%E5%9D%80">网址 ,目测是做本地存储的

https://d8d913s460fub.cloudfront.net/krpanocloud/webvr_localstorage.html?v=4

因为部分代码是加密的,没办法处理,经过为排查解决办法就是

找到 plugins/we...

阅读全文>>