PHP开启错误显示,php.ini配置修改 PHP
前言
PHP报错了,页面白屏或者500,啥也不显示,不知道哪错了?开了错误显示就能看到具体错误了。本文讲怎么改php.ini开启错误显示。
一、为什么不显示错误
生产环境为了安全,默认不显示错误,防止暴露敏感信息(路径、数据库密码等)。
但开发的时候就不方便了,啥也看不到。
二、找到php.ini
找php.ini位置
php --ini
输出:
Loaded Configuration File: /etc/php.ini
或者:
/etc/php/7.4/cli/php.ini
注意:CLI和FPM的php.ini可能不一样。
看当前加载的是哪个
写个phpinfo:
<?php
phpinfo();
?>
浏览器访问,看Loaded Configuration File。
三、修改php.ini
1. 显示错误
display_errors = On
2. 报错级别
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
或者全开:
error_reporting = E_ALL
3. 错误日志
log_errors = On
error_log = /var/log/php_errors.log
4. 显示启动错误
display_startup_errors = On
四、改完重启
PHP-FPM
systemctl restart php-fpm
或者:
systemctl reload php-fpm
Apache
systemctl restart httpd
五、代码里临时开启
不想改php.ini,在代码开头加:
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
或者:
ini_set('error_reporting', E_ALL);
ini_set('display_errors', 1);
六、常见错误类型
E_ALL
所有错误和警告。
E_ERROR
致命运行错误,脚本停止。
E_WARNING
运行时警告,脚本继续。
E_NOTICE
运行时注意,比如未定义变量。
七、常见坑
坑1:改了php.ini不生效
改的不是实际加载的那个php.ini。
解决: 用 php --ini 看实际加载的是哪个。
坑2:FPM和CLI的php.ini不一样
命令行改了,网页上不生效。
原因: CLI和FPM用不同的php.ini。
解决: 改FPM的那个,比如 /etc/php/7.4/fpm/php.ini。
坑3:页面白屏
可能是语法错误,php.ini都没加载起来。
检查: 看PHP错误日志。
坑4:开了错误显示有安全风险
生产环境不能开!
注意: 排查完一定要改回去。
坑5:.htaccess里覆盖了
有些主机在.htaccess里设了php_flag。
检查: 看看.htaccess里有没有。
八、生产环境配置
生产环境不要开display_errors,但要开日志:
display_errors = Off
log_errors = On
error_log = /var/log/php_errors.log
error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED
九、查看错误日志
PHP错误日志
tail -f /var/log/php_errors.log
Nginx错误日志
tail -f /var/log/nginx/error.log
Apache错误日志
tail -f /var/log/httpd/error_log
十、快速排查
第一步:代码里临时开
ini_set('display_errors', 1);
error_reporting(E_ALL);
第二步:看具体报错
刷新页面,看报什么错。
第三步:解决完删掉
改完了把代码里的ini_set删掉,或者改回生产配置。
总结
记住:
display_errors = On显示错误error_reporting = E_ALL显示所有错误- 改完重启php-fpm
- 生产环境关掉display_errors,开log_errors
- 代码里可以用ini_set临时开
开发环境推荐:
display_errors = On
error_reporting = E_ALL
log_errors = On
生产环境推荐:
display_errors = Off
log_errors = On
error_reporting = E_ALL & ~E_NOTICE
遇到问题加QQ23979811 协助处理
ThinkPHP6 500报错,开启错误日志查看原因 PHP
前言
ThinkPHP6网站突然500报错,页面啥也不显示,不知道哪错了?本文讲怎么开启错误显示和日志,快速定位问题。
一、为什么500不显示错误
生产环境为了安全,关闭了错误显示,直接返回500,不显示具体错误信息。
这是对的,不然用户能看到你的代码路径、数据库密码等敏感信息。
但排查问题就不方便了。
二、临时开启错误显示
修改 .env 文件
项目根目录下有个 .env 文件:
APP_DEBUG = true
把 APP_DEBUG 改成 true。
刷新页面,就能看到具体错误了。
注意
排查完记得改回 false! 生产环境不能开debug。
三、开启日志记录
就算不开debug,错误也会记录到日志文件里。
日志配置
config/log.php 文件:
return [
// 默认日志通道
'default' => 'file',
// 日志通道列表
'channels' => [
'file' => [
// 日志记录方式
'type' => 'File',
// 日志保存目录
'path' => '',
// 单文件日志写入
'single' => false,
// 独立日志级别
'apart_level' => [],
// 最大日志文件数量
'max_files' => 30,
],
],
];
日志位置
默认在 runtime/log/ 目录下。
按日期分目录:
runtime/log/
├── 2026-10/
│ ├── 08.log
│ ├── 07.log
│ └── 06.log
└── 2026-09/
└── ...
查看今天的错误
tail -f runtime/log/2026-10/08.log
四、常见500错误排查
1. 目录权限问题
runtime目录没权限写:
Permission denied
解决:
chmod -R 755 runtime
chown -R www:www runtime
2. 缺少扩展
Call to undefined function xxx()
解决: 装对应的PHP扩展。
3. 数据库连接失败
SQLSTATE[HY000] [1045] Access denied
检查: 数据库配置对不对。
.env 或 config/database.php:
'hostname' => '127.0.0.1',
'database' => '数据库名',
'username' => '用户名',
'password' => '密码',
4. 路由错误
Route not found
检查: 路由配置对不对。
5. 模板找不到
template not exists
检查: 模板文件路径对不对。
五、手动写日志
代码里可以手动写日志:
// 记录错误
Trace::error('这是一个错误信息');
// 记录警告
Trace::warning('这是一个警告');
// 记录信息
Trace::info('这是一个信息');
或者用助手函数:
trace('这是调试信息', 'debug');
六、查看PHP错误日志
除了ThinkPHP的日志,PHP本身也有错误日志。
查看PHP错误日志位置
php --ini | grep error_log
Nginx错误日志
tail -f /var/log/nginx/error.log
七、常见排查步骤
第一步:开debug看具体错误
改 .env:
APP_DEBUG = true
刷新页面,看具体报什么错。
第二步:看ThinkPHP日志
tail -f runtime/log/2026-10/08.log
第三步:看Nginx错误日志
tail -f /var/log/nginx/error.log
第四步:看PHP错误日志
tail -f /var/log/php-fpm/error.log
第五步:解决完改回debug
改完 .env:
APP_DEBUG = false
八、常见坑
坑1:开了debug还是不显示
缓存没清。
解决: 删除runtime目录下的缓存:
rm -rf runtime/cache/*
坑2:日志目录没权限
stream_socket_client(): unable to connect
runtime目录没写权限。
解决:
chmod -R 755 runtime
坑3:生产环境开着debug
危险!用户能看到你的敏感信息。
解决: 排查完立刻改回 APP_DEBUG = false。
坑4:日志太大占磁盘
日志越积越多,磁盘满了。
解决: 设 max_files,自动删除旧日志:
'max_files' => 30,
坑5:502和500搞混
- 500:PHP代码错误
- 502:PHP-FPM挂了
区分: 看Nginx错误日志。
总结
记住:
- 改
.env的APP_DEBUG = true临时看错误 - 生产环境必须改回
false - 日志在
runtime/log/目录 - 排查完记得清缓存
- 500是PHP代码问题,502是FPM问题
排查流程:
开debug → 看具体报错 → 看ThinkPHP日志 → 看Nginx日志 → 解决问题 → 关debug
遇到问题加QQ23979811 协助处理
PHP FPM进程过多导致服务器卡顿优化 PHP
前言
PHP FPM进程太多,把服务器内存吃满,网站卡顿甚至502?本文讲怎么优化PHP FPM进程数。
一、为什么FPM进程多会卡
PHP FPM每处理一个请求,就开一个进程。
进程开多了:
- 内存占满
- CPU切换不过来
- 服务器卡顿
- 甚至OOM被杀
二、查看当前进程数
查看PHP FPM进程
ps aux | grep php-fpm
数一下有多少个进程。
看每个进程占多少内存
ps aux | grep php-fpm | awk '{print $6/1024 "MB"}'
算一下总内存
ps aux | grep php-fpm | awk '{sum+=$6} END {print sum/1024 "MB"}'
三、FPM配置文件在哪
CentOS
/etc/php-fpm.d/www.conf
或者:
/etc/php/7.4/fpm/pool.d/www.conf
Ubuntu
/etc/php/7.4/fpm/pool.d/www.conf
四、进程管理模式
PHP FPM有三种进程管理模式:
1. static(静态)
固定进程数,启动就开这么多。
pm = static
pm.max_children = 50
2. dynamic(动态)
默认模式,按需开进程。
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35
3. ondemand
没人访问的时候不开进程,来了请求才开。
pm = ondemand
pm.max_children = 50
pm.process_idle_timeout = 10s
五、怎么算合适的进程数
公式
pm.max_children = 可用内存 / 每个进程平均内存
例子
- 服务器2G内存
- 系统和其他服务占1G
- 剩下1G给PHP
- 每个PHP进程平均占40M
pm.max_children = 1024 / 40 ≈ 25
所以设25个进程差不多。
别设太大
设太大了,内存不够用,就会OOM。
六、推荐配置
小服务器(1G内存)
pm = dynamic
pm.max_children = 10
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 5
中服务器(2-4G内存)
pm = dynamic
pm.max_children = 30
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
大服务器(8G以上)
pm = dynamic
pm.max_children = 80
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 40
七、其他优化参数
request_terminate_timeout
单个请求最长执行时间,超时就杀掉。
request_terminate_timeout = 30s
slow log
慢日志,看看哪个请求慢。
slowlog = /var/log/php-fpm/slow.log
request_slowlog_timeout = 10s
php_admin_value[memory_limit]
每个PHP进程的内存限制。
php_admin_value[memory_limit] = 128M
八、改完配置重载
systemctl reload php-fpm
或者:
systemctl restart php-fpm
九、验证效果
看进程数
ps aux | grep php-fpm | wc -l
看内存
free -h
看负载
top
十、常见坑
坑1:max_children设太大
比如2G内存设了100个进程,内存直接爆。
解决: 按上面的公式算,别拍脑袋。
坑2:改完配置不生效
忘了重载。
解决:
systemctl reload php-fpm
坑3:进程数一直涨
有慢请求,占着进程不放。
检查:
request_terminate_timeout = 30s
设个超时,超时就杀。
坑4:502 Bad Gateway
进程都忙不过来,Nginx连不上FPM。
解决: 加max_children,或者优化慢请求。
坑5:用了static模式
static固定进程数,不用就浪费内存。
推荐: 用dynamic或ondemand。
十一、排查步骤
第一步:看是不是FPM进程多
ps aux | grep php-fpm | wc -l
第二步:看内存够不够
free -h
第三步:看有没有慢请求
tail -f /var/log/php-fpm/slow.log
第四步:调整配置
改www.conf里的pm.max_children等参数。
第五步:重载验证
systemctl reload php-fpm
总结
记住:
- 进程数别设太大,按内存算
- 公式:可用内存 / 每个进程平均内存
- 推荐用dynamic模式
- 设个request_terminate_timeout,防慢请求占着进程
- 改完记得reload
推荐配置:
pm = dynamic
pm.max_children = 30
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
request_terminate_timeout = 30s
遇到问题加QQ23979811 协助处理
PHP 字符串处理函数 PHP
PHP 字符串处理函数
字符串处理是 PHP 最常用的操作,这些函数一定要会。
1. 截取字符串
// 截取前n个字符
substr("hello world", 0, 5); // hello
// 中文截取(用mb_substr)
mb_substr("你好世界", 0, 2, "utf-8"); // 你好
2. 替换字符串
// str_replace 替换
str_replace("world", "PHP", "hello world"); // hello PHP
// 只替换第一次出现
str_replace("a", "b", "aaa", $count);
3. 查找字符串
// 查找位置(找不到返回false)
strpos("hello world", "world"); // 6
// 注意:用 === 0 判断开头
if (strpos($str, "hello") === 0) {
echo "以hello开头";
}
4. 大小写转换
// 转小写
strtolower("Hello"); // hello
// 转大写
strtoupper("hello"); // HELLO
// 首字母大写
ucfirst("hello"); // Hello
// 每个单词首字母大写
ucwords("hello world"); // Hello World
5. 去除空白
// 去除两边空格
trim(" hello "); // hello
// 去左边
ltrim(" hello "); // hello
// 去右边
rtrim(" hello "); // hello
6. 字符串拼接
// 用点拼接
$str = "hello" . " " . "world";
// 多变量拼接
$a = "hello";
$b = "world";
$c = "$a $b"; // hello world
7. 分割和合并
// 分割成数组
$arr = explode(",", "a,b,c"); // ["a", "b", "c"]
// 数组合并成字符串
$str = implode(",", $arr); // a,b,c
8. 常用技巧
1)判断是否包含字符串:
if (strpos($str, "hello") !== false) {
echo "包含hello";
}
2)反转字符串:
strrev("hello"); // olleh
3)字符串长度:
strlen("hello"); // 5
mb_strlen("你好", "utf-8"); // 2
总结
PHP 字符串处理要点:
- substr 截取,注意中文用 mb_substr
- str_replace 替换
- strpos 查找,用 !== false 判断
- trim 去空格
- explode/implode 分割合并
- 注意中文编码问题,用 mb 开头的函数
写 PHP,字符串函数天天用。
PHP 常用设计模式 PHP
PHP 常用设计模式
设计模式是写好代码的经验总结,常用的几种要掌握。
1. 单例模式
整个项目只有一个实例,比如数据库连接。
class Db
{
private static $instance = null;
private function __construct() {}
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
}
$db = Db::getInstance();
2. 工厂模式
根据参数创建不同的对象。
class Factory
{
public static function make($type)
{
$class = ucfirst($type);
return new $class();
}
}
$user = Factory::make('user');
$order = Factory::make('order');
3. 观察者模式
一个对象状态变化,通知所有观察者。
interface Observer
{
public function update($event);
}
class Event
{
private $observers = [];
public function add(Observer $observer)
{
$this->observers[] = $observer;
}
public function trigger($event)
{
foreach ($this->observers as $ob) {
$ob->update($event);
}
}
}
4. 常用场景
- 单例: 数据库、日志、配置
- 工厂: 创建不同类的对象
- 观察者: 事件触发、消息通知
- 策略: 不同支付方式
- 适配器: 兼容不同接口
5. 设计原则
- 单一职责:一个类只做一件事
- 开闭原则:对扩展开放,对修改关闭
- 依赖倒置:依赖抽象不依赖具体
总结
PHP 常用设计模式要点:
- 单例模式:只创建一个实例
- 工厂模式:统一创建对象
- 观察者:事件通知
- 理解设计原则
- 不要为了模式而模式
设计模式是工具,解决问题才是目的。
PHP Composer 使用指南 PHP
PHP Composer 使用指南
Composer 是 PHP 的依赖管理工具,做开发必备。
1. 安装 Composer
# 下载安装
curl -sS https://getcomposer.org/installer | php
# 移动到全局
mv composer.phar /usr/local/bin/composer
# 验证
composer -V
2. 国内镜像加速
# 阿里镜像
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
3. 常用命令
1)初始化项目:
composer init
2)安装依赖:
# 安装所有依赖
composer install
# 安装指定包
composer require monolog/monolog
# 安装开发依赖
composer require --dev phpunit/phpunit
3)更新依赖:
# 更新所有依赖
composer update
# 更新指定包
composer update monolog/monolog
4)删除依赖:
composer remove monolog/monolog
4. composer.json 说明
{
"name": "test/project",
"description": "测试项目",
"require": {
"php": ">=7.0",
"monolog/monolog": "^2.0"
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
5. 自动加载
// 引入自动加载
require __DIR__ . '/vendor/autoload.php';
// 使用类
$log = new Monolog\Logger('name');
6. 常用操作
composer install:根据 lock 文件安装composer update:更新依赖composer dump-autoload:重新生成自动加载
总结
Composer 使用要点:
- 安装 Composer
- 配置国内镜像
- require 安装依赖
- autoload 自动加载
- install/update 管理依赖
做 PHP 开发,Composer 一定要会用。
PHP 会话管理详解 PHP
PHP 会话管理详解
Session 是 PHP 做用户登录状态管理的核心功能,搞懂它很重要。
1. 什么是 Session
- Cookie: 存在客户端(浏览器)
- Session: 存在服务器端
- 通过 SessionID 关联用户
2. 基础用法
// 开启会话(必须放在最前面)
session_start();
// 存数据
$_SESSION['user_id'] = 1;
$_SESSION['username'] = "test";
// 取数据
echo $_SESSION['username'];
// 判断是否登录
if (isset($_SESSION['user_id'])) {
echo "已登录";
} else {
echo "未登录";
}
// 销毁会话
session_destroy();
3. 登录验证示例
// 登录页
session_start();
if ($_POST['password'] == "123456") {
$_SESSION['user'] = $_POST['username'];
header("Location: dashboard.php");
}
// 验证页
session_start();
if (!isset($_SESSION['user'])) {
header("Location: login.php");
exit;
}
4. 常用配置
php.ini 里的配置:
; 会话有效期(分钟)
session.gc_maxlifetime = 1440
; Cookie 有效期(秒)
session.cookie_lifetime = 0
; 是否只允许 HTTP 访问 Cookie
session.cookie_httponly = On
5. 常见问题
1)session 丢失:
- 检查是否有输出(session_start 前不能有空格)
- 检查 Cookie 是否被禁用
2)多服务器共享 Session:
- 存在数据库里
- 存在 Redis 里
- 不要用文件 Session
3)安全问题:
- 登录后重新生成 SessionID
session_regenerate_id(); - 防止 Session 固定攻击
6. Cookie vs Session
| 对比 | Cookie | Session |
|---|---|---|
| 存储位置 | 客户端 | 服务器端 |
| 大小限制 | 4KB | 无限制 |
| 安全性 | 低 | 高 |
| 生命周期 | 可长期保存 | 浏览器关闭就没了 |
7. 登出销毁
session_start();
// 清除所有 session 变量
$_SESSION = array();
// 清除 session cookie
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time()-42000, '/');
}
// 销毁 session
session_destroy();
总结
PHP 会话管理要点:
- session_start() 必须在最前面
- 登录验证用 $_SESSION 判断
- 生产环境用 Redis 存 Session
- 登录后重新生成 SessionID 防攻击
做用户系统,Session 是必须掌握的。
PHP 错误处理机制 PHP
PHP 错误处理机制
做开发离不开错误处理,搞懂 PHP 的错误机制才能写出健壮的代码。
1. 错误级别
PHP 错误分几个级别:
1)致命错误(E_ERROR)
- 脚本停止执行
- 比如调用不存在的类、方法
2)警告(E_WARNING)
- 脚本继续执行
- 比如包含不存在的文件
3)注意(E_NOTICE)
- 不影响执行
- 比如使用未定义的变量
2. 错误报告配置
php.ini 里的配置:
; 开发环境:显示所有错误
display_errors = On
error_reporting = E_ALL
; 生产环境:不显示错误,记录日志
display_errors = Off
log_errors = On
error_reporting = E_ALL & ~E_NOTICE
3. 自定义错误处理
// 设置错误报告级别
error_reporting(E_ALL);
// 自定义错误处理函数
set_error_handler(function($errno, $errstr, $errfile, $errline) {
echo "错误:[$errno] $errstr 在 $errfile 第 $errline 行";
return true; // 阻止默认错误处理
});
// 测试
echo $undefined_var;
4. 异常处理
try {
if (!file_exists("test.txt")) {
throw new Exception("文件不存在");
}
$file = fopen("test.txt", "r");
} catch (Exception $e) {
echo "错误:" . $e->getMessage();
} finally {
echo "\n执行完成";
}
5. 错误日志
// 记录错误日志
error_log("这是一条错误日志", 3, "/tmp/php_errors.log");
// 手动触发错误
trigger_error("自定义错误", E_USER_WARNING);
6. 开发 vs 生产
开发环境:
- 显示错误
- 所有错误都报告
- 方便调试
生产环境:
- 不显示错误(防止泄露敏感信息)
- 记录错误日志
- 只报告致命错误和警告
7. 常用技巧
1)错误抑制符 @
// 不推荐,会影响性能
@include("config.php");
2)die/exit
// 简单粗暴
if (! $db) {
die("数据库连接失败");
}
3)抛异常
- 推荐用异常处理
- 代码更清晰,容易维护
总结
PHP 错误处理要点:
- 开发环境显示错误,生产环境记录日志
- 用 try-catch 处理异常
- 错误日志要记录,方便排查
- 不要用 @ 错误抑制符
写代码多做错误处理,线上少踩坑。
PHP 数组常用函数 PHP
PHP 数组常用函数
数组是 PHP 最常用的数据结构,数组函数用熟了开发效率翻倍。整理一份常用清单。
1. 数组创建和遍历
// 索引数组
$arr1 = [1, 2, 3];
// 关联数组
$arr2 = ['name' => '张三', 'age' => 25];
// 遍历
foreach ($arr2 as $key => $value) {
echo "$key: $value\n";
}
2. 数组增删改查
// 追加元素
$arr[] = 4;
array_push($arr, 5, 6);
// 头部插入
array_unshift($arr, 0);
// 删除末尾元素
array_pop($arr);
// 删除头部元素
array_shift($arr);
// 删除指定元素
unset($arr[0]);
3. 数组合并和拆分
// 合并数组
$arr1 = [1, 2];
$arr2 = [3, 4];
$merged = array_merge($arr1, $arr2); // [1,2,3,4]
// 拆分
$slice = array_slice($arr, 0, 2);
4. 查找和过滤
// 判断键是否存在
array_key_exists('name', $arr);
// 判断值是否存在
in_array('张三', $arr);
// 查找值对应的键
array_search('张三', $arr);
// 数组过滤
$filtered = array_filter([1, 2, 3, 4], function($n) {
return $n > 2;
}); // [3,4]
5. 排序
sort($arr); // 升序
rsort($arr); // 降序
asort($arr); // 按值升序,保留键
ksort($arr); // 按键升序
6. 常用操作
// 数组长度
count($arr);
// 去重
array_unique($arr);
// 反转
array_reverse($arr);
// 随机取一个
array_rand($arr);
7. 实际应用
统计数组中出现次数:
$counts = array_count_values(['a', 'b', 'a', 'c', 'a']);
// ['a' => 3, 'b' => 1, 'c' => 1]
二维数组按某列排序:
$users = [
['name' => '张三', 'age' => 25],
['name' => '李四', 'age' => 20]
];
array_multisort(array_column($users, 'age'), SORT_ASC, $users);
总结
PHP 数组函数非常多,日常开发记住这些常用的就够了:
- 增删改查:array_push / array_pop / unset
- 合并拆分:array_merge / array_slice
- 查找过滤:in_array / array_filter
- 排序:sort / asort / ksort
数组是 PHP 的灵魂,多用多练就熟了。
PHP 错误处理最佳实践 PHP
PHP 错误处理最佳实践
错误处理是 PHP 开发最容易忽略但最重要的环节,写好了排查问题事半功倍,写不好线上出问题抓瞎。
1. 错误级别
PHP 有不同的错误级别:
- E_ERROR:致命错误,脚本停止
- E_WARNING:警告,脚本继续
- E_NOTICE:注意,一般是不规范写法
- E_PARSE:语法解析错误
// 开发环境显示所有错误
error_reporting(E_ALL);
ini_set('display_errors', 1);
// 生产环境不显示错误,只记日志
error_reporting(E_ALL);
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', '/var/log/php/error.log');
2. 错误 vs 异常
PHP 里错误和异常是两回事:
- 错误:语法错误、内存不足这种,用 try/catch 抓不住
- 异常:业务层面的错误,比如数据库连接失败
PHP 7+ 大部分错误会抛 Error 异常,也可以抓了。
3. try/catch 用法
try {
// 可能出错的代码
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
} catch (PDOException $e) {
// 捕获异常
echo "数据库连接失败:" . $e->getMessage();
// 记日志
error_log("DB Error: " . $e->getMessage());
}
4. 自定义错误处理
// 设置自定义错误处理器
set_error_handler(function($errno, $errstr, $errfile, $errline) {
// 把错误转成异常抛出
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});
// 设置异常处理器
set_exception_handler(function($e) {
// 所有未捕获的异常都到这里
error_log("Uncaught: " . $e->getMessage());
echo "系统繁忙,请稍后再试";
});
// 注册关闭函数,抓致命错误
register_shutdown_function(function() {
$error = error_get_last();
if ($error && in_array($error['type'], [E_ERROR, E_PARSE])) {
error_log("Fatal: " . $error['message']);
}
});
5. 开发 vs 生产环境
开发环境:
- 打开 display_errors,错误直接显示在页面
- 打开所有错误级别
- 详细的报错信息方便调试
生产环境:
- 关闭 display_errors,不要把错误暴露给用户
- 错误全部写到日志文件
- 页面显示友好的"系统错误"提示
6. 常用错误处理技巧
// 1. 用 @ 抑制错误不好,应该判断
// 不好:
$file = @file_get_contents('config.php');
// 好:
$file = file_exists('config.php') ? file_get_contents('config.php') : null;
// 2. 不要把数据库错误信息直接返回给前端
// 不好:
echo $e->getMessage();
// 好:
error_log($e->getMessage());
echo json(['code' => 500, 'msg' => '系统错误']);
// 3. 日志要分级
error_log('信息:用户登录', 3, '/var/log/info.log');
error_log('警告:登录失败次数过多', 3, '/var/log/warn.log');
error_log('错误:数据库连接失败', 3, '/var/log/error.log');
7. 总结
PHP 错误处理核心:
- 开发环境显示错误,生产环境只记日志
- try/catch 捕获业务异常
- set_exception_handler 兜底
- 不要把错误细节暴露给用户
- 日志分级,方便排查
搞懂这些,线上出问题排查效率翻倍。
PHP Composer 入门指南 PHP
PHP Composer 入门指南
Composer 是 PHP 的依赖管理工具,现在做 PHP 开发不用 Composer 几乎不可能。
1. 安装 Composer
# Linux/Mac
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
# Windows 直接下载安装包
# https://getcomposer.org/Composer-Setup.exe
验证安装:
composer -V
2. 换国内镜像(必须)
官方镜像太慢,一定要换国内镜像:
# 阿里云镜像
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
# 腾讯云镜像
composer config -g repo.packagist composer https://mirrors.tencent.com/composer/
3. 初始化项目
# 进入项目目录
cd myproject
# 初始化 composer.json
composer init
或者手动创建 composer.json:
{
"name": "my/project",
"require": {
"monolog/monolog": "^2.0"
}
}
4. 常用命令
# 安装依赖
composer install
# 更新依赖
composer update
# 安装某个包
composer require monolog/monolog
# 卸载某个包
composer remove monolog/monolog
# 自动加载
composer dump-autoload
5. 自动加载
// 引入自动加载文件
require __DIR__ . '/vendor/autoload.php';
// 然后就可以直接用第三方库了
$log = new Monolog\Logger('name');
6. composer.json 详解
{
"name": "项目名",
"description": "项目描述",
"type": "project",
"require": {
"php": ">=7.4",
"monolog/monolog": "^2.0",
"guzzlehttp/guzzle": "^7.0"
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
7. 版本号说明
^2.0:兼容 2.0 到 3.0(不包含 3.0)~2.0:兼容 2.0 到 2.1(不包含 2.1)*:任意版本2.0.*:2.0.x 版本
总结
Composer 核心:
- 安装:一行命令
- 换镜像:必须换国内源
- 常用:install / update / require / remove
- 自动加载:require vendor/autoload.php
搞懂这些,Composer 日常开发就够用了。
PHP 字符串处理技巧 PHP
PHP 字符串处理常用技巧
字符串处理是 PHP 开发最常用的操作,掌握这些函数,写代码效率翻倍。
1. 截取字符串
// 截取前 5 个字符
substr("hello world", 0, 5); // hello
// 截取从第 6 个开始到结尾
substr("hello world", 6); // world
// 中文字符串截取(用 mb_)
mb_substr("你好世界", 0, 2, "UTF-8"); // 你好
注意:中文要用 mb_substr,不能用 substr,否则会乱码。
2. 替换字符串
// str_replace(替换所有)
str_replace("world", "PHP", "hello world"); // hello PHP
// str_ireplace(不区分大小写)
str_ireplace("WORLD", "PHP", "hello world");
// preg_replace(正则替换)
preg_replace("/\d/", "", "abc123def"); // abcdef
3. 查找字符串
// 查找位置(找不到返回 false)
strpos("hello world", "world"); // 6
// 查找最后出现位置
strrpos("hello world hello", "hello"); // 12
// 判断是否包含(PHP 8+)
str_contains("hello world", "world"); // true
// 判断开头
str_starts_with("hello world", "hello"); // true
// 判断结尾
str_ends_with("hello world", "world"); // true
4. 格式化字符串
// 去除首尾空格
trim(" hello "); // hello
// 只去左边/右边
ltrim(" hello"); // hello
rtrim("hello "); // hello
// 转小写/大写
strtolower("Hello"); // hello
strtoupper("hello"); // HELLO
// 首字母大写
ucfirst("hello"); // Hello
// 每个单词首字母大写
ucwords("hello world"); // Hello World
5. 字符串和数组转换
// 字符串转数组
explode(",", "a,b,c"); // ["a","b","c"]
// 数组转字符串
implode(",", ["a","b","c"]); // a,b,c
// 重复字符串
str_repeat("ab", 3); // ababab
// 字符串长度
strlen("hello"); // 5
mb_strlen("你好", "UTF-8"); // 2
6. 常用技巧
// 生成随机字符串
substr(md5(time()), 0, 8);
// 脱敏手机号
substr_replace("13812345678", "****", 3, 4); // 138****5678
// 截取摘要(带省略号)
mb_strlen($text) > 10 ? mb_substr($text, 0, 10) . "..." : $text;
// 清除 HTML 标签
strip_tags("<p>hello</p>"); // hello
总结
PHP 字符串处理核心函数:
- 截取:substr / mb_substr
- 替换:str_replace / preg_replace
- 查找:strpos / str_contains
- 格式化:trim / strtolower / ucwords
- 转换:explode / implode
记住这些,日常开发基本够用了。
PHP 数组操作技巧 PHP
PHP 数组操作技巧
数组是 PHP 最常用的数据结构,掌握这些技巧,写代码效率翻倍。
1. 数组合并
// 索引数组合并
$arr1 = [1, 2];
$arr2 = [3, 4];
$result = array_merge($arr1, $arr2); // [1,2,3,4]
// 关联数组合并,后面覆盖前面
$arr1 = ['a' => 1, 'b' => 2];
$arr2 = ['b' => 3, 'c' => 4];
$result = array_merge($arr1, $arr2); // ['a'=>1, 'b'=>3, 'c'=>4]
2. 数组去重
// 一维数组去重
$arr = [1, 2, 2, 3, 3, 3];
$result = array_unique($arr); // [1,2,3]
// 二维数组按字段去重
$users = [
['id' => 1, 'name' => '张三'],
['id' => 2, 'name' => '李四'],
['id' => 1, 'name' => '张三'],
];
$ids = array_column($users, 'id');
$unique = array_unique($ids);
3. 数组排序
// 升序
sort($arr);
// 降序
rsort($arr);
// 按键排序
ksort($arr);
// 按值排序,保留键
asort($arr);
4. 数组过滤
// 过滤空值
$arr = [1, 0, '', null, 'a'];
$result = array_filter($arr); // [1, 'a']
// 自定义过滤
$result = array_filter($arr, function($value) {
return $value > 2;
});
5. 数组取值
// 取某一列
$names = array_column($users, 'name');
// 取交集
$arr1 = [1, 2, 3];
$arr2 = [2, 3, 4];
$result = array_intersect($arr1, $arr2); // [2,3]
// 取差集
$result = array_diff($arr1, $arr2); // [1]
6. 常用技巧
// 判断键是否存在
isset($arr['key']);
array_key_exists('key', $arr);
// 随机取一个
$value = array_rand($arr);
// 打乱数组
shuffle($arr);
// 数组合并成字符串
$str = implode(',', $arr);
// 字符串转数组
$arr = explode(',', $str);
总结
PHP 数组函数非常丰富,常用的就这些:合并、去重、排序、过滤、取值。把这些记熟,日常开发基本够用了。
PHP 安全最佳实践 PHP
PHP 开发必须注意的安全问题
PHP 开发最容易出安全问题,几个常见坑一定要避开。
1. SQL 注入
最常见的安全漏洞。用户输入拼接到 SQL 里,被注入恶意 SQL。
解决方案:用预处理语句
// 不要这样
$sql = "SELECT * FROM users WHERE id = " . $_GET['id'];
// 要这样
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_GET['id']]);
2. XSS 跨站脚本
用户输入直接输出到页面,被注入恶意 JS。
解决方案:输出时转义
echo htmlspecialchars($user_input);
3. CSRF 跨站请求伪造
别人伪造你的请求操作。
解决方案:加 Token 验证
// 表单里加 Token
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['token']; ?>">
// 后端验证
if ($_POST['csrf_token'] !== $_SESSION['token']) {
die('CSRF 攻击');
}
4. 文件上传漏洞
用户上传 PHP 文件,直接拿到 webshell。
解决方案:
- 限制文件类型
- 重命名文件
- 上传目录不执行 PHP
5. 密码明文存储
数据库被拖库,密码全泄露。
解决方案:用 password_hash
$hash = password_hash($password, PASSWORD_DEFAULT);
// 验证
password_verify($password, $hash);
6. 错误信息泄露
生产环境把报错直接展示给用户,暴露路径和代码。
解决方案:关闭 display_errors
display_errors = Off
log_errors = On
总结
PHP 安全的核心:用户输入都不可信,所有输出都要转义,数据库操作用预处理。安全开发意识比工具更重要。
PHP 8.0 新特性 PHP
PHP 8.0 有哪些重磅更新
PHP 8.0 是一个大版本更新,带来了很多革命性的特性。
1. JIT 编译
PHP 8.0 引入了 JIT(即时编译),性能大幅提升,计算密集型场景性能翻倍。
2. 命名参数
array_filter(array: $array, callback: fn($x) => $x > 0);
不用按顺序传参,写参数名就行,可读性更好。
3. 枚举 Enum
enum Status: string
{
case Pending = 'pending';
case Active = 'active';
case Rejected = 'rejected';
}
4. 构造函数属性提升
class User {
public function __construct(
public int $id,
public string $name
) {}
}
不用再写 $this->id = $id 了,构造函数直接定义属性。
5. 空安全运算符
$user?->getAddress()?->city;
不用层层判断 null,有 null 直接返回 null。
6. Match 表达式
$result = match($status) {
200 => '成功',
404 => '未找到',
default => '未知'
};
比 switch 更简洁,还能直接赋值。
7. 联合类型
function foo(int|string $input) {}
参数可以是多种类型。
总结
PHP 8.0 是现代 PHP 的起点,类型系统更完善,语法更现代。新项目强烈推荐用 PHP 8.0+。
PHP 7.4 新特性 PHP
PHP 7.4 有哪些实用新特性
PHP 7.4 是 7.x 系列的最后一个版本,带来了不少语法糖和性能优化,至今还有很多项目在用。
1. 类型属性
类的属性可以声明类型了:
class User {
public int $id;
public string $name;
public ?string $email;
}
之前属性不能写类型,只能靠 PHPDoc 注释,现在直接写在代码里,IDE 提示更准确。
2. 箭头函数
支持短闭包:
$users = array_map(fn($user) => $user['name'], $users);
比传统的 function ($user) use (...) {} 简洁多了,自动捕获外层变量。
3. 空合并赋值
$data['user'] ??= [];
相当于:
if (!isset($data['user'])) {
$data['user'] = [];
}
4. 数组展开
$arr1 = [1, 2, 3];
$arr2 = [4, 5, 6];
$merged = [...$arr1, ...$arr2];
5. 数字字面量分隔
$amount = 1_000_000;
$price = 9_999.99;
大数字用下划线分隔,可读性提升。
6. 性能提升
PHP 7.4 比 7.3 性能提升约 10%,内存占用也更少。
总结
PHP 7.4 虽然不是大版本,但实用特性很多,尤其是类型属性和箭头函数,写起来舒服不少。新项目建议直接上 PHP 8+,老项目升级到 7.4 也很稳妥。
PHP Session 与 Cookie:会话管理实战指南 PHP
前言
HTTP 是无状态的,你每次请求服务器都不认识你。Session 和 Cookie 就是用来解决这个问题的。本文讲清楚 PHP 中 Session 和 Cookie 的用法。
一、Cookie 是什么
Cookie 是存在浏览器里的小数据,每次请求自动带给服务器。
设置 Cookie
setcookie("username", "张三", time() + 3600, "/");
参数说明:
- 第一个参数:名称
- 第二个参数:值
- 第三个参数:过期时间(时间戳)
- 第四个参数:路径
读取 Cookie
echo $_COOKIE['username'];
删除 Cookie
setcookie("username", "", time() - 3600, "/");
把过期时间设成过去就行。
二、Session 是什么
Session 是存在服务器上的数据,通过 Session ID 识别用户。
启动 Session
session_start();
注意:必须在输出之前调用,不然会报错。
存数据
$_SESSION['user_id'] = 1;
$_SESSION['username'] = '张三';
读数据
echo $_SESSION['username'];
删除单个数据
unset($_SESSION['user_id']);
销毁 Session
session_destroy();
三、Session 和 Cookie 的区别
| 对比 | Cookie | Session |
|---|---|---|
| 存储位置 | 浏览器 | 服务器 |
| 大小限制 | 4KB | 无限制 |
| 安全性 | 低(用户能改) | 高 |
| 生命周期 | 可设置 | 默认浏览器关闭就没 |
四、登录功能示例
登录页
<?php
session_start();
if ($_POST) {
$username = $_POST['username'];
$password = $_POST['password'];
// 验证用户名密码
if ($username == 'admin' && $password == '123456') {
$_SESSION['user_id'] = 1;
$_SESSION['username'] = $username;
header('Location: dashboard.php');
exit;
} else {
echo "用户名或密码错误";
}
}
?>
判断是否登录
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
?>
退出登录
<?php
session_start();
session_destroy();
header('Location: login.php');
exit;
?>
五、Session 配置
修改 Session 有效期
ini_set('session.gc_maxlifetime', 3600); // 1小时
session_start();
修改 Session 存储路径
session_save_path('/tmp/sessions');
session_start();
用 Redis 存储 Session
生产环境推荐用 Redis 存 Session,默认文件存储性能差。
php.ini 配置:
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379"
六、安全问题
1. Session 劫持
别人拿到你的 Session ID,就能冒充你。
防护:
- 用 HTTPS
- Session ID 定期更换
- 绑定 IP(不太推荐,IP 会变)
2. Cookie 劫持
别人拿到你的 Cookie,就能冒充你。
防护:
- 设置 HttpOnly,JS 读不到
- 设置 Secure,只在 HTTPS 下传
- 设置 SameSite,防止 CSRF
setcookie("token", $token, [
'expires' => time() + 3600,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
]);
3. CSRF 攻击
别人伪造你的请求。
防护:
- 表单加 CSRF Token
- 验证 Referer
七、常见坑
- session_start() 在输出之后:报错 headers already sent
- Session 没销毁:退出登录后还能访问
- Cookie 大小限制:别存太多东西,超过 4KB 就丢
- Session 文件太多:默认文件存储,大了要清理
八、最佳实践
- 敏感数据用 Session,别存 Cookie
- Cookie 加 HttpOnly 和 Secure
- 生产环境用 Redis 存 Session
- 登录成功后重新生成 Session ID,防止固定攻击
// 登录成功后
session_regenerate_id(true);
总结
Session 和 Cookie 的核心要点:
- Cookie 存在浏览器,Session 存在服务器
- session_start() 必须在输出之前调用
- Session 更安全,Cookie 更轻量
- 生产环境用 Redis 存 Session
- Cookie 加 HttpOnly 和 Secure,防劫持
登录、权限、购物车,都离不开 Session 和 Cookie。搞懂这俩,PHP 后端才算入门。
PHP Composer 入门:依赖管理完全指南 PHP
前言
Composer 是 PHP 的依赖管理工具,就像 Node 的 npm、Python 的 pip。现在写 PHP 项目,不会 Composer 根本没法干活。本文讲清楚 Composer 的核心用法。
一、安装 Composer
Linux / Mac
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
Windows
去官网下载安装包,一路下一步就行。
验证安装
composer -V
二、初始化项目
# 在项目目录下
composer init
会问你几个问题,一路回车就行,然后会生成 composer.json 文件。
composer.json 长什么样
{
"name": "yourname/project",
"description": "项目描述",
"require": {
"monolog/monolog": "^2.0"
}
}
三、安装依赖
1. 安装所有依赖
composer install
会根据 composer.lock 文件安装指定版本的依赖。
2. 添加新依赖
composer require monolog/monolog
会自动加到 composer.json 里,然后安装。
3. 安装指定版本
composer require monolog/monolog:^2.0
版本号说明
^2.0:2.0 到 3.0 之前(不包括 3.0)~2.0:2.0 到 2.1 之前(不包括 2.1)*:任意版本2.0.*:2.0 开头的版本
四、自动加载
Composer 最爽的就是自动加载,不用自己写 require。
引入自动加载
<?php
require 'vendor/autoload.php';
// 直接用类,不用 require
$log = new Monolog\Logger('name');
PSR-4 自动加载
在 composer.json 里配置:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
然后执行:
composer dump-autoload
这样 App\User 类就会从 src/User.php 加载。
五、常用命令
| 命令 | 作用 |
|---|---|
composer install |
安装所有依赖 |
composer update |
更新所有依赖 |
composer require 包名 |
添加依赖 |
composer remove 包名 |
删除依赖 |
composer dump-autoload |
重新生成自动加载 |
composer show |
查看已安装的包 |
composer self-update |
更新 Composer 本身 |
六、开发环境依赖
有些包只在开发时用,比如测试工具:
composer require --dev phpunit/phpunit
线上部署的时候,不安装开发依赖:
composer install --no-dev
七、中国镜像
国外源太慢,换中国镜像:
# 阿里云镜像
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
# 腾讯云镜像
composer config -g repo.packagist composer https://mirrors.tencent.com/composer/
换完之后速度飞起来。
八、composer.lock 的作用
- 记录当前安装的依赖版本
- 团队成员 install 的时候,装的版本一模一样
- 一定要提交到 Git
git add composer.json composer.lock
git commit -m "update composer"
九、常见坑
- 没装 composer.lock:团队成员装的版本不一样,出 bug
- 自动加载不生效:改了 autoload 配置,忘了 dump-autoload
- 版本冲突:两个包依赖同一个库的不同版本
- 国内太慢:不换镜像,下载半天
十、最佳实践
- composer.json 和 composer.lock 都提交 Git
- 线上用 install --no-dev,不要用 update
- 用中文镜像,加速下载
- 改了自动加载配置,记得 dump-autoload
总结
Composer 的核心要点:
- require 添加依赖,install 安装依赖
- vendor/autoload.php 是自动加载入口
- composer.lock 要提交 Git,保证版本一致
- 换国内镜像,速度快很多
- 开发依赖用 --dev,线上不装
学会 Composer,PHP 开发效率提升一倍。
PHP 数组常用操作:从排序到过滤的完整指南 PHP
前言
数组是 PHP 里最常用的数据结构,没有之一。PHP 提供了 100 多个数组函数,很多人只知道其中几个。本文整理最常用的数组操作。
一、创建数组
<?php
// 索引数组
$arr1 = [1, 2, 3, 4, 5];
// 关联数组
$arr2 = ['name' => '张三', 'age' => 18];
// 空数组
$arr3 = [];
二、添加元素
<?php
$arr = [1, 2, 3];
// 末尾添加
$arr[] = 4; // [1, 2, 3, 4]
array_push($arr, 5); // [1, 2, 3, 4, 5]
// 开头添加
array_unshift($arr, 0); // [0, 1, 2, 3, 4, 5]
// 关联数组添加
$user = ['name' => '张三'];
$user['age'] = 18; // ['name' => '张三', 'age' => 18]
三、删除元素
<?php
$arr = [1, 2, 3, 4, 5];
// 删除末尾元素
array_pop($arr); // [1, 2, 3, 4]
// 删除开头元素
array_shift($arr); // [2, 3, 4]
// 删除指定元素
unset($arr[1]); // [0 => 2, 2 => 4],注意索引不连续
四、查找元素
<?php
$arr = ['a', 'b', 'c'];
// 值是否存在
in_array('b', $arr); // true
// 键是否存在
$user = ['name' => '张三', 'age' => 18];
array_key_exists('name', $user); // true
// 查找值的键
array_search('b', $arr); // 1
五、数组长度
<?php
$arr = [1, 2, 3];
count($arr); // 3
sizeof($arr); // 3(count 的别名)
六、排序
索引数组排序
<?php
$arr = [3, 1, 2, 5, 4];
sort($arr); // [1, 2, 3, 4, 5] 升序
rsort($arr); // [5, 4, 3, 2, 1] 降序
关联数组排序
<?php
$age = ['张三' => 20, '李四' => 18, '王五' => 25];
asort($age); // 按值升序,保持键名
ksort($age); // 按键升序
arsort($age); // 按值降序
krsort($age); // 按键降序
自定义排序
<?php
$users = [
['name' => '张三', 'age' => 20],
['name' => '李四', 'age' => 18],
['name' => '王五', 'age' => 25],
];
// 按 age 升序
usort($users, function ($a, $b) {
return $a['age'] <=> $b['age'];
});
七、数组过滤
array_filter()
<?php
$arr = [1, 2, 3, 4, 5, 6];
// 过滤出偶数
$even = array_filter($arr, function ($n) {
return $n % 2 == 0;
});
// [2, 4, 6]
array_map()
<?php
$arr = [1, 2, 3, 4, 5];
// 每个元素乘以 2
$doubled = array_map(function ($n) {
return $n * 2;
}, $arr);
// [2, 4, 6, 8, 10]
array_walk()
<?php
$arr = ['a' => 1, 'b' => 2];
array_walk($arr, function (&$value, $key) {
$value = $value * 10;
});
// ['a' => 10, 'b' => 20]
八、数组合并
<?php
$arr1 = [1, 2];
$arr2 = [3, 4];
// 数组合并
$merged = array_merge($arr1, $arr2); // [1, 2, 3, 4]
// + 运算符(保留第一个数组的键)
$result = $arr1 + $arr2;
九、数组切片
<?php
$arr = [1, 2, 3, 4, 5];
// 从第 2 个开始取 3 个
$slice = array_slice($arr, 1, 3); // [2, 3, 4]
// 从末尾取
$last = array_slice($arr, -2); // [4, 5]
十、键值操作
<?php
$user = ['name' => '张三', 'age' => 18];
// 所有键
array_keys($user); // ['name', 'age']
// 所有值
array_values($user); // ['张三', 18]
// 翻转键值
array_flip($user); // ['张三' => 'name', 18 => 'age']
十一、常用操作速查表
| 操作 | 函数 |
|---|---|
| 数组长度 | count() |
| 查找值 | in_array() |
| 查找键 | array_key_exists() |
| 排序 | sort() / asort() / ksort() |
| 过滤 | array_filter() |
| 映射 | array_map() |
| 合并 | array_merge() |
| 切片 | array_slice() |
十二、常见坑
- unset 后索引不连续:用 array_values() 重新索引
- array_merge 和 + 的区别:数字键 array_merge 会重新索引,+ 不会
- in_array 严格模式:加第三个参数 true 防止类型转换
- sort 会改变原数组:不是返回新数组
总结
PHP 数组操作的核心要点:
- 增删改查:array_push/pop/unshift/shift/unset
- 查找判断:in_array/array_key_exists/array_search
- 排序:sort/asort/ksort/usort
- 处理:array_filter/array_map/array_walk
- 合并切片:array_merge/array_slice
数组用好了,PHP 开发效率能提升一倍。
PHP 字符串处理:常用函数和最佳实践指南 PHP
前言
字符串处理是 PHP 开发中最常用的操作之一。很多人写了很多年代码,却还是用错字符串函数。本文整理最常用的字符串处理函数和最佳实践。
一、字符串长度
strlen()
<?php
$str = "hello";
echo strlen($str); // 5
注意:strlen 按字节算,中文会出问题。
mb_strlen()
<?php
$str = "你好";
echo mb_strlen($str, 'UTF-8'); // 2
echo strlen($str); // 6(3个字节一个汉字)
记住:处理中文一定要用 mb_ 系列函数。
二、字符串查找
strpos()
查找字符串第一次出现的位置:
<?php
$str = "hello world";
$pos = strpos($str, "world");
echo $pos; // 6
坑: 如果没找到返回 false,如果找到的位置是 0,也返回 0。
<?php
// 错误写法
if (strpos($str, "hello")) {
// 如果 hello 在第 0 位,这里不会执行
}
// 正确写法
if (strpos($str, "hello") !== false) {
// 这样才对
}
strrpos()
查找字符串最后一次出现的位置。
stripos() / strripos()
不区分大小写的查找。
三、字符串替换
str_replace()
<?php
$str = "hello world";
echo str_replace("world", "PHP", $str); // hello PHP
数组替换:
<?php
echo str_replace(
["hello", "world"],
["hi", "PHP"],
"hello world"
); // hi PHP
substr_replace()
替换字符串的一部分:
<?php
echo substr_replace("hello world", "PHP", 6); // hello PHP
preg_replace()
正则替换:
<?php
// 把多个空格变成一个
echo preg_replace('/\s+/', ' ', "hello world"); // hello world
四、字符串截取
substr()
<?php
$str = "hello world";
echo substr($str, 0, 5); // hello
echo substr($str, 6); // world
中文截取要用 mb_substr():
<?php
$str = "你好世界";
echo mb_substr($str, 0, 2, 'UTF-8'); // 你好
五、字符串分割与连接
explode()
<?php
$str = "a,b,c,d";
$arr = explode(",", $str);
print_r($arr); // ['a', 'b', 'c', 'd']
implode() / join()
<?php
$arr = ['a', 'b', 'c'];
echo implode(",", $arr); // a,b,c
六、字符串去空格
trim()
<?php
$str = " hello ";
echo trim($str); // "hello",去掉两边空格
echo ltrim($str); // "hello ",去掉左边空格
echo rtrim($str); // " hello",去掉右边空格
七、大小写转换
<?php
$str = "Hello World";
echo strtolower($str); // hello world
echo strtoupper($str); // HELLO WORLD
echo ucfirst($str); // Hello world
echo ucwords($str); // Hello World
八、HTML 转义
htmlspecialchars()
输出到 HTML 时一定要转义,防止 XSS:
<?php
$str = "<script>alert('xss')</script>";
echo htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
// 输出 <script>alert('xss')</script>
htmlentities()
更彻底的转义,把所有 HTML 都转义。
九、JSON 处理
json_encode()
<?php
$arr = ['name' => '张三', 'age' => 18];
echo json_encode($arr, JSON_UNESCAPED_UNICODE);
// {"name":"张三","age":18}
记住:加 JSON_UNESCAPED_UNICODE,不然中文会变成 \uXXXX。
json_decode()
<?php
$json = '{"name":"张三","age":18}';
$obj = json_decode($json); // 对象
$arr = json_decode($json, true); // 数组
十、常见坑
- strpos 用 == 判断:位置 0 和 false 会混淆
- 中文用 strlen/substr:按字节算,中文会乱码
- 输出 HTML 不转义:XSS 漏洞
- json_encode 不加 JSON_UNESCAPED_UNICODE:中文变 \uXXXX
- 字符串拼接用 . 不用 +:PHP 是 . 号
总结
PHP 字符串处理的核心要点:
- 中文用 mb_ 系列函数,不要用 strlen/substr
- strpos 用 !== false 判断,不要用 ==
- 输出 HTML 一定要 htmlspecialchars 转义
- json_encode 加 JSON_UNESCAPED_UNICODE
- 字符串拼接用 . 号,不要用 + 号
掌握这些,字符串处理就不会出大问题了。