PHP遍历关联数组

PHP遍历关联数组

引言

关联数组用键名而非数字下标组织数据,配置项、接口返回的JSON转成数组后都是关联数组。遍历要同时拿到键和值,foreach是最常用的方式,不同场景配合array_keys、array_walk更灵活。

foreach取键和值

$user = ['name'=>'刘馨怡','age'=>26,'city'=>'连云港'];
foreach ($user as $key => $value) {
    echo "$key: $value\n";
}

$key => $value同时拿到键名和值,最通用。

只取值

foreach ($user as $value) {
    echo $value;
}

不需要键名时省略$key。

用键名取单个值

echo $user['name'];
// 判断键是否存在
if (isset($user['email'])) {
    echo $user['email'];
}

取单值直接下标访问,先isset避免未定义键报错。

array_keys取所有键

$keys = array_keys($user);
print_r($keys); // ['name','age','city']

需要单独处理键名列表时用。

array_walk回调遍历

array_walk($user, function($value, $key) {
    echo "$key => $value";
});

适合把遍历逻辑封装成回调。

二维关联数组遍历

$list = [
    ['id'=>1,'name'=>'A'],
    ['id'=>2,'name'=>'B']
];
foreach ($list as $row) {
    echo $row['id'].'-'.$row['name'];
}

循环里再按键名取子元素。

注意事项

  • foreach不会改变原数组指针,比each安全;
  • 遍历中不要随意增删键,可能导致迭代异常;
  • 关联数组键名大小写敏感;
  • 值可能为null时用array_key_exists判断键是否存在,isset对null返回false;
  • 大数组遍历时注意内存,避免在循环内重复计算。

总结

关联数组遍历首选foreach的$key => $value形式,单值直接下标加isset判断,取键名用array_keys,封装逻辑用array_walk,二维数组外层foreach内层按键取值。掌握这几种就能应对配置、接口数据等绝大多数场景。


emer 发布于  2026-10-19 07:27 

PHP cURL发送POST

PHP cURL发送POST

引言

后端对接第三方接口、登录模拟、提交表单,PHP最常用cURL扩展发HTTP请求。file_get_contents只能简单GET,cURL能控制POST、请求头、Cookie、超时和错误处理,是对接API的标配。

基础POST表单

$ch = curl_init('https://api.example.com/login');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
    'username' => 'user01',
    'password' => '123456',
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 结果返回字符串而非直接输出
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$res = curl_exec($ch);
$err = curl_error($ch);
curl_close($ch);

POSTFIELDS传数组即multipart表单,接口收到的是form-data。

发送JSON

对接REST接口要手动编码并声明头:

$json = json_encode(['name' => '测试', 'age' => 18]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Authorization: Bearer ' . $token,
]);

注意JSON方式POSTFIELDS传字符串,别传数组。

带Cookie维持登录

curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');   // 第一次保存
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookie.txt');  // 第二次读取

模拟登录再访问需鉴权页面时,用cookie文件维持会话。

错误与状态码处理

if ($err) { echo '请求失败:' . $err; }
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$data = json_decode($res, true);

别只看返回体,必须判断$code和curl_error,500/404也要处理。

注意事项

  • 关SSL校验仅限本地测试,生产保留CURLOPT_SSL_VERIFYPEER;
  • 超时必须设,防止接口慢拖垮进程;
  • HTTPS证书异常先排查证书链,别长期关闭校验;
  • 敏感token放请求头,别写进URL参数;
  • 用完curl_close释放句柄。

总结

cURL POST先init,设CURLOPT_POST和POSTFIELDS,表单传数组、JSON传字符串并带头,RETURNTRANSFER取回结果,配合超时、错误判断和状态码,生产保留SSL校验。掌握这套就能稳定对接绝大多数第三方API。


emer 发布于  2026-10-19 07:23 

PHP二维数组排序

PHP二维数组排序

引言

从数据库查出的列表通常是二维数组,要按价格、销量、时间某一字段升降序排列,单维的sort/rsort直接用会把结构打乱。需要按指定键排序,常用array_multisort和usort两种思路。

array_multisort按字段排

$goods = [
    ['name' => 'A商品', 'price' => 99],
    ['name' => 'B商品', 'price' => 39],
    ['name' => 'C商品', 'price' => 69],
];
// 抽出price列作为排序依据
$price = array_column($goods, 'price');
array_multisort($price, SORT_DESC, $goods);
print_r($goods); // 价格从高到低

array_column先取单列,multisort按该列降序,主数组同步跟着重排。

多字段组合排序

先按销量降序,销量相同再按价格升序:

$sales = array_column($goods, 'sales');
$price = array_column($goods, 'price');
array_multisort($sales, SORT_DESC, $price, SORT_ASC, $goods);

usort自定义比较

规则复杂或中文拼音排序时用usort:

usort($goods, function($a, $b) {
    return $a['price'] <=> $b['price']; // 升序
});

太空船运算符<=>比较大小,降序交换$a、$b即可。

注意事项

  • array_multisort会改变原数组顺序,需要原数据先备份;
  • 比较的字段类型要一致,避免字符串和数字混比;
  • usort是稳定排序,同值元素相对位置保留;
  • 中文排序可配合intl扩展或自定义映射,别直接靠默认strcmp;
  • 数据量大时,优先在SQL层ORDER BY,PHP排序只做内存小列表。

总结

简单单字段排序用array_column加array_multisort,多字段依次传入,复杂规则用usort加<=>比较。能在MySQL ORDER BY解决的就别把数据拉到PHP再排,减轻内存压力。


emer 发布于  2026-10-19 07:20 

PHP字符串截取方法

PHP字符串截取方法

引言

截取标题摘要、手机号中间脱敏、按字数截断列表页,是PHP开发里最高频的操作。很多人直接用substr处理中文,结果出现半个汉字的乱码,关键在于substr按字节切,中文UTF-8占3个字节。

substr按字节截取

$str = "hello世界";
echo substr($str, 0, 5); // 输出 hello,中文场景容易切坏

substr只适合纯英文ASCII,遇到中文按字节偏移,可能把一个汉字拆成两半。

mb_substr按字符截取

处理中文要用多字节扩展mbstring:

echo mb_substr("hello世界", 0, 5, 'UTF-8');

第四个参数指定编码UTF-8,按"字"而不是"字节"切,中文完整不烂。

带省略号的摘要截断

function cutText($text, $len = 20) {
    if (mb_strlen($text, 'UTF-8') <= $len) return $text;
    return mb_substr($text, 0, $len, 'UTF-8') . '...';
}

先mb_strlen算字符长度,超长再截并补省略号,列表页摘要常用。

手机号中间脱敏

$phone = "13812345678";
echo substr($phone, 0, 3) . '****' . substr($phone, -4);
// 138****5678

手机号纯数字,substr完全够用,用-4取后四位。

注意事项

  • 中文必须mb_substr并显式传UTF-8,别依赖默认编码;
  • 确认服务器装了mbstring扩展,php -m查看;
  • 表情、生僻字占多个字节,更要按字符切;
  • 截断前先判断长度,避免补省略号反而超长。

总结

纯英文数字用substr,含中文统一mb_substr指定UTF-8,摘要先mb_strlen判断再补省略号,手机号脱敏用substr取头尾。选对函数就不会出现半个汉字乱码。


emer 发布于  2026-10-19 07:16 

PHP数组去重排序

PHP数组去重排序

引言

数组是PHP最常用的数据结构,去重和排序是开发中反复出现的基础需求。掌握内置函数的正确用法,比自己写循环更高效,也更不容易出错。

一维数组去重

$arr = [3, 1, 2, 3, 1, 5];
$unique = array_unique($arr);
//结果保留首次出现的值,键名不变

注意array_unique默认按字符串比较,去重后键名可能不连续,需要重新索引:

$unique = array_values(array_unique($arr));

关联数组按字段去重

$users = [
    ['id'=>1,'name'=>'张三'],
    ['id'=>2,'name'=>'李四'],
    ['id'=>1,'name'=>'张三副本'],
];
$seen = [];
$unique = array_filter($users, function($item) use (&$seen) {
    if (in_array($item['id'], $seen)) return false;
    $seen[] = $item['id'];
    return true;
});

排序函数区分

  • sort():值升序,重置键名;
  • rsort():值降序;
  • asort():值升序,保留键名;
  • ksort():按键名升序;
  • krsort():按键名降序。
$score = ['张三'=>88,'王五'=>95,'李四'=>76];
arsort($score); //按分数降序,保留姓名键名
print_r($score);

自定义排序

$users = [['age'=>20],['age'=>35],['age'=>28]];
usort($users, function($a, $b) {
    return $a['age'] <=> $b['age']; //太空船运算符比较
});

注意事项

  • array_unique对多维数组不能直接按字段去重;
  • sort系列会改变原数组,返回bool;
  • 中文排序建议用Collator或mb方式;
  • 去重后及时array_values重置索引,避免后续遍历异常。

总结

一维去重用array_unique加array_values,多维按字段用array_filter配合标记数组。排序先想清是否保留键名,普通值排序用sort/rsort,关联数组用asort/ksort,复杂规则用usort自定义比较。


emer 发布于  2026-10-18 07:30 

PHP错误日志排查

PHP错误日志排查

引言

线上页面白屏、500错误,前台看不到具体原因,靠猜很难定位。正确做法是开启并查看PHP错误日志,从日志里拿到文件、行号、错误类型,再针对性修复。

先确认日志位置

在phpinfo页面搜索error_log,或查看php.ini配置:

#查看php.ini错误日志配置
php -i | grep error_log
#常见位置
tail -f /var/log/php-fpm/www-error.log
tail -f /var/log/httpd/php_errors.log

宝塔、面板环境一般在日志菜单里可直接打开PHP错误日志。

开发环境临时显示错误

<?php
ini_set('display_errors',1);
ini_set('error_reporting',E_ALL);
error_reporting(E_ALL);

生产环境不要直接display_errors到页面,统一写日志。

日志格式解读

一条错误日志通常包含:错误级别、报错文件、行号、错误信息。

[12-Oct-2026 07:00:00] PHP Fatal error:
Call to undefined function xxx() in /www/app/index.php on line 18

含义:第18行调用了不存在的函数,检查函数是否引入、命名是否拼错。

常见错误类型

  • Fatal error:致命错误,程序中断,如调用不存在的类、函数;
  • Warning:警告不中断,如参数类型不对;
  • Notice:提示,未定义变量;
  • Deprecated:废弃语法,未来版本不兼容。

排查流程

  1. 复现问题,记录访问时间;
  2. 按时间过滤日志,定位对应报错;
  3. 打开报错文件对应行号;
  4. 修复后清空日志再验证。

总结

PHP排错第一步永远是看错误日志,而不是反复刷新页面。开发环境显示错误,生产环境写日志,按时间和行号快速定位,养成记录日志的习惯。


emer 发布于  2026-10-18 07:23 

Composer国内镜像配置

Composer国内镜像配置

引言

PHP项目用Composer安装依赖时,默认从packagist.org国外源拉取,国内网络经常超时、下载极慢。配置国内镜像源后,安装速度能提升数倍,是PHP开发环境必备操作。

全局配置方法

终端执行下面命令,把全局镜像换成国内源:

composer config -g repos.packagist composer https://mirrors.aliyun.com/composer/

执行后写入用户全局配置,所有项目生效。

单个项目配置

只给当前项目换源,在项目目录执行:

composer config repositories.packagist composer https://mirrors.aliyun.com/composer/

常见国内镜像

验证与切换

#查看当前源
composer config -g repos

#回到官方源
composer config -g --unset repos.packagist

注意事项

  • 镜像只加速包下载,不影响代码本身;
  • 生产环境尽量锁定composer.lock版本;
  • 个别新包国内镜像同步延迟,临时可切官方源;
  • 配置后先清缓存再安装:composer clearcache。

总结

Composer换源是国内PHP开发第一步,全局配置阿里云镜像即可解决大部分超时问题。安装依赖前先清缓存,项目锁定lock保证团队版本一致。


emer 发布于  2026-10-18 07:21 

PHP文件上传校验

PHP文件上传校验

引言

文件上传是网站高频功能,也是最容易出安全问题的地方。只判断后缀名,黑客可以把木马改名为图片绕过,上传到服务器执行。上传必须做多层校验。

必须校验的内容

  1. 检查上传错误码,确认文件确实上传成功;
  2. 限制文件大小,防止超大文件占满磁盘;
  3. 白名单校验扩展名,只允许jpg/png等指定类型;
  4. 读取文件真实MIME类型,不能只信前端传的type;
  5. 重新生成随机文件名,避免原文件名覆盖或路径穿越;
  6. 上传目录禁止执行PHP脚本。

基础校验示例

<?php
$allow = ['jpg','png','gif'];
$ext = strtolower(pathinfo($_FILES['file']['name'],PATHINFO_EXTENSION));
if(!in_array($ext,$allow)){
    exit('类型不允许');
}
if($_FILES['file']['size'] > 2*1024*1024){
    exit('文件过大');
}
//获取真实类型
$info = getimagesize($_FILES['file']['tmp_name']);
if(!$info) exit('不是合法图片');
//随机重命名
$newName = uniqid().'.'.$ext;
move_uploaded_file($_FILES['file']['tmp_name'],'./upload/'.$newName);

服务端加固

  • Nginx/Apache配置上传目录禁止解析php;
  • 图片上传后重新压缩生成,破坏木马脚本;
  • 关闭上传目录的执行权限;
  • 定期扫描上传目录文件。

总结

文件上传安全核心:不信任前端、白名单、校验真实类型、随机改名、目录隔离。多层校验才能防止webshell上传,保护服务器安全。


emer 发布于  2026-10-18 07:19 

PHP请求参数过滤

PHP请求参数过滤

引言

Web接口接收GET、POST参数,如果不做过滤校验,容易出现SQL注入、XSS、业务逻辑漏洞。PHP开发接口时,参数过滤是安全第一道防线,所有外部输入都不可信。

基础过滤思路

  1. 类型强制转换:数字参数直接转为int;
  2. 长度限制,防止传入超大字符串;
  3. 正则匹配手机号、邮箱等固定格式;
  4. 输出到页面时做html转义,防止XSS;
  5. 入库前转义或者使用PDO预编译防止注入。

代码示例

<?php
// 获取GET参数
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
$name = trim($_GET['name'] ?? '');

// 长度校验
if(mb_strlen($name)>50){
    exit("参数过长");
}

// 输出到页面,防XSS
echo htmlspecialchars($name,ENT_QUOTES);

框架层面最佳实践

TP6、Laravel等框架自带验证器,推荐优先使用框架验证,不用手写大量if判断。

// ThinkPHP6验证示例
$validate = new \think\Validate([
    'id'=>'require|integer',
    'name'=>'require|max:50'
]);

避坑点

不要简单依靠addslashes防御注入,推荐PDO预处理语句;参数过滤不要只在前端校验,后端必须二次校验,前端校验可被绕过。

总结

任何外部传入的数据都要校验,区分类型校验、长度校验、格式校验、输出转义四层防护,降低Web安全漏洞风险,是PHP项目开发的基础规范。


emer 发布于  2026-10-18 07:14 

PHP trait复用代码方案

PHP trait复用代码方案

引言

在PHP面向对象开发中,类只支持单继承,一个子类只能继承一个父类。当多个不同类需要共用一段逻辑,又不想强行继承同一父类时,Trait特性就是最佳解决方案。Trait可以把可复用的方法抽离出来,在多个类中引入,打破单继承限制,广泛用于项目公共方法封装。

Trait基础原理

Trait本质不是类,不能实例化,仅用于封装方法。使用use关键字在类内部引入,引入后,类可以直接调用Trait内定义的方法。

优先级规则:本类方法 > trait方法 > 父类方法。当方法重名时,优先执行当前类定义的代码。

代码示例

<?php
trait LogTrait {
    public function writeLog(string $msg) {
        $log = date('Y-m-d H:i:s') . " : " . $msg . PHP_EOL;
        file_put_contents('./run.log', $log, FILE_APPEND);
    }
}

class UserService {
    use LogTrait;
    public function addUser() {
        $this->writeLog("新增用户数据");
    }
}

$user = new UserService();
$user->addUser();
?>

多Trait冲突处理

一个类可以同时use多个Trait。多个Trait存在同名方法会直接报错,这时使用insteadof指定优先使用哪个Trait的方法,as可以给方法起别名。

trait A{ public function test(){echo "A";}}
trait B{ public function test(){echo "B";}}
class Demo{
    use A,B{
        A::test insteadof B;
        B::test as bTest;
    }
}

适用场景与坑点

✅ 适用场景:多类共用日志、验证码、文件上传等公共逻辑

⚠️ 注意:Trait不能定义静态常量;尽量不要在Trait写大量业务逻辑,只放通用工具方法,避免代码难以维护。

总结

Trait弥补了PHP单继承短板,适合项目中抽取通用能力。合理使用可以减少大量重复代码,但不能滥用,否则会造成代码逻辑分散,增加后期维护成本。


emer 发布于  2026-10-18 07:09 

PHP 批量导入CSV数据完整指南(完整版)

最近在项目里又遇到了批量导入CSV数据的典型问题,索性把解决方法整理成这篇文章,希望能帮到遇到同样问题的同学。


emer 发布于  2026-10-14 07:09 

PHP 字符串反转入门教程(新手必看)

很多初学者在学习PHP时,都会遇到字符串反转相关的问题。网上的资料零散且质量参差不齐,本文尝试用一篇文章把字符串反转讲清楚。


emer 发布于  2026-10-14 07:09 

PHP 批量导入CSV数据最佳实践(2026最新整理)

PHP的生态非常丰富,但批量导入CSV数据依然是最常用的功能点之一。本文整理了最实用的几种实现方式。


emer 发布于  2026-10-14 07:09 

PHP 手机号码归属地校验避坑指南(2026最新整理)

很多线上 Bug 的根源,都在于对手机号码归属地校验的理解不够深入。本文从常见错误出发,反推正确的使用姿势。


emer 发布于  2026-10-14 07:07 

PHP 读写CSV文件进阶技巧分享(2026最新整理)

本文面向PHP初学者,用通俗的语言讲解读写CSV文件,读完即可动手实践。


emer 发布于  2026-10-14 07:06 

PHP 敏感词过滤完整指南(建议收藏)

很多初学者在学习PHP时,都会遇到敏感词过滤相关的问题。网上的资料零散且质量参差不齐,本文尝试用一篇文章把敏感词过滤讲清楚。


emer 发布于  2026-10-14 07:06 

PHP 生成唯一订单号实战详解(2026最新整理)

熟练掌握生成唯一订单号,是写好PHP代码的基本功。本文循序渐进,从概念到示例一次讲透。


emer 发布于  2026-10-14 07:06 

PHP 数组排序快速上手指南

最近在项目里又遇到了数组排序的典型问题,索性把解决方法整理成这篇文章,希望能帮到遇到同样问题的同学。


emer 发布于  2026-10-14 07:03 

PHP 计算两个日期相差天数入门教程(2026最新整理)

很多线上 Bug 的根源,都在于对计算两个日期相差天数的理解不够深入。本文从常见错误出发,反推正确的使用姿势。


emer 发布于  2026-10-13 07:20 

PHP 中文转拼音进阶技巧分享

项目赶进度的时候,中文转拼音这类基础问题最容易浪费调试时间。提前掌握本文的内容,可以少走很多弯路。


emer 发布于  2026-10-13 07:18 
'); })();