PHP 中将字符串转换为字符数组
方法1:使用 str_split() 函数
$string = "Hello"; $array = str_split($string); print_r($array); // 输出:Array ( [0] => H [1] => e [2] => l [3] => l [4] => o )
方法2:使用 preg_split() 正则表达式分割
preg_split() 函数配合 UTF-8 模式可以正确处理多字节字符(如中文、日文、表情符号等),将它们分割为单个字符的数组。
$string = "你好,World";
$array = preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY);
print_r($array);
// 输出:Array ( [0] => 你 [1] => 好 [2] => , [3] => W [4] => o [5] => r [6] => l [7] => d )
方法3:使用 mb_str_split() 处理多字节字符(PHP 7.4+)
$string = "你好"; $array = mb_str_split($string); print_r($array); // 输出:Array ( [0] => 你 [1] => 好 )
preg_split()参数说明:
'//u' - 正则表达式模式,u 修饰符表示 UTF-8 模式
$string - 要分割的字符串
-1 - 表示不限制分割次数
PREG_SPLIT_NO_EMPTY - 过滤掉空元素
PHP按目标比例和尺寸缩小并裁切图片
重点是关于图片翻转、旋转部分的处理
/**
* 按目标比例和尺寸缩小并裁切图片,如果原图尺寸小于目标尺寸,则只按比例裁切
* @param $img_name 原图片名称(不是路径)
* @param $width 目标图片宽度,如果原图宽度不等于目标宽度,则原图按目标比例缩放后再裁切
* @param $width 目标图片高度
*/
private function img_convert_do($img_name, $width, $height){
//$new_name=date('YmdHis').my_str_shuffle(5,'number,lower').substr($img_name,strrpos($img_name,'.'));
$new_name=date('YmdHis').my_str_shuffle(5,'number,lower').'.jpg';
$old_img=SRC_PATH.$img_name;
$new_img=DST_PATH.$new_name;
/*
exif_read_data($old_img)结果如下:
Array
(
[FileName] => a.jpg
[FileDateTime] => 1750318340
[FileSize] => 17175
[FileType] => 2
[MimeType] => image/jpeg
[SectionsFound] => ANY_TAG, IFD0, EXIF
[COMPUTED] => Array
(
[html] => width="536" height="404"
[Height] => 404
[Width] => 536
[IsColor] => 1
[ByteOrderMotorola] => 1
)
[Orientation] => 8
[Exif_IFD_Pointer] => 318
[UndefinedTag:0xEA1C] =>
)
*/
$exif_res=@exif_read_data($old_img);
if($exif_res===false){
$size_arr = @getimagesize($old_img);
if(!is_array($size_arr)){
exit('图片尺寸获取失败:'.$img_name);
}
$w = $size_arr[0];
$h= $size_arr[1];
//printr($size_arr);
}else{
$w=$exif_res['COMPUTED']['Width'];
$h=$exif_res['COMPUTED']['Height'];
//printr($exif_res);
}
$source = imagecreatefromstring(file_get_contents($old_img));
switch(array_item($exif_res,'Orientation')){
case 1: //无翻转
break;
case 2: //水平翻转
imageflip($source,IMG_FLIP_HORIZONTAL);
break;
case 3: //旋转180度
$source = imagerotate($source,180,0);
break;
case 4: //垂直翻转
imageflip($source,IMG_FLIP_VERTICAL);
break;
case 5: //顺时针旋转90度+水平翻转
$source = imagerotate($source,-90,0);
imageflip($source,IMG_FLIP_HORIZONTAL);
break;
case 6: //顺时针旋转90度
$source = imagerotate($source,-90,0);
break;
case 7: //逆时针旋转90度+水平翻转
$source = imagerotate($source,90,0);
imageflip($source,IMG_FLIP_HORIZONTAL);
break;
case 8: //逆时针旋转90度
$source = imagerotate($source,90,0);
break;
default: //png等无方向属性
}
switch(array_item($exif_res,'Orientation')){
case 5:
case 6:
case 7:
case 8:
//旋转90度的图片扶正后要宽高值要互换
$tmp=$w;
$w=$h;
$h=$tmp;
unset($tmp);
break;
}
$src_w=$w;
$src_h=$h;
if($w/$h < $width/$height){
$h=ceil($w*$height/$width);
}else if($w/$h > $width/$height){
$w=ceil($width*$h/$height);
}else{
//比例一致时,如果原图小于100K则直接复制
if(filesize($old_img)<100*1024){
copy($old_img,$new_img);
return $new_name;
}
}
if($w<$width){
$width=$w;
$height=$h;
}
//echo $w,'x',$h,'<br>',$width,'x',$height,'<br>';return;
//新建真彩色图像
$im = imagecreatetruecolor($width, $height);
//为图像分配颜色
//$color = imagecolorallocate($im, 255,255,255);
//从指定坐标开始填充颜色
//imagefill($im, 0,0, $color);
//从字符串的图像流中新建图像,可以自动识别文件类型,但是比 imagecreatefromjpeg 等多消耗内存
//totxt($old_img, FCPATH.'photo.txt', true);
//$source = imagecreatefromstring(file_get_contents($old_img));
/*
从 x、y 坐标 src_x、src_y 开始,将 src_image 的一部分复制到 dst_image 上,
宽度为 src_width,高度为 src_height。定义的部分将被复制到 x,y 坐标 dst_x 和 dst_y 上。
imagecopy(
GdImage $dst_image,
GdImage $src_image,
int $dst_x,
int $dst_y,
int $src_x,
int $src_y,
int $src_width,
int $src_height
): bool
从 src_image 位置(src_x、src_y)开始取出一个宽度为 src_width 高度为 src_height 的矩形区域,
并将其放置在 dst_image 中位置从(dst_x、dst_y)开始宽度为 dst_width 高度为 dst_height 的矩形区域中。
imagecopyresampled(
GdImage $dst_image,
GdImage $src_image,
int $dst_x,
int $dst_y,
int $src_x,
int $src_y,
int $dst_width,
int $dst_height,
int $src_width,
int $src_height
): bool
输出图象到浏览器或文件
image 由图象创建函数(例如imagecreatetruecolor())返回的 GdImage 对象。
file 文件保存的路径或者已打开的流资源(此方法返回后自动关闭该流资源),如果未设置或为 null,将会直接输出原始图象流。
quality 为可选项,范围从 0(最差质量,文件最小)到 100(最佳质量,文件最大)。默认值(-1)使用 IJG 默认的质量值(大约 75)。
imagejpeg(GdImage $image, resource|string|null $file = null, int $quality = -1): bool
*/
//执行剪裁(高质量重采样)
//($src_h-$h)/4 此处是4而不是2的原因:尽量从上边开始剪裁,避免上边剪裁过大,导致头到照片顶部留白太小甚至剪到头
imagecopyresampled($im, $source, 0,0, $src_w>$w?($src_w-$w)/2:0,$src_h>$h?($src_h-$h)/3:0, $width,$height, $w,$h);
imagedestroy($source);
//保存到文件
imagejpeg($im, $new_img, 90);
imagedestroy($im);
//exit('ok');
return $new_name;
}php导出数据到csv
/**
* 格式化导出到excel文件(csv格式)的数据
* @param mixed $item array | string
*/
function format_export_string($item){
if(is_array($item) || is_object($item)){
$array = array();
foreach($item as $k=>$v){
$array[$k] = format_export_string($v);
}
return $array;
}else{
if(is_numeric($item)){ //数值型
$item = (string)$item;
if(preg_match("/^-?\d{1,11}$/", $item)){ //不超过11位的整数
return $item;
}else if(is_lng($item) && $item!='0' && substr($item,0,1)=='0'){ //以0开头的数字字符串
return '="' . $item . '"';
}else{
return '="' . $item . '"';
}
}else{
if(strpos($item, ',') !== FALSE || strpos($item, "\r") !== FALSE || strpos($item, "\n") !== FALSE){ //逗号、回车、换行
if(strpos($item, '"') !== FALSE){ //有双引号
return '"' . str_replace('"', '""', $item) . '"';
}else{
return '"' . $item . '"';
}
}else if(!check_datetime($item) && preg_match("/^[\+\-\*\/\%\^\(\)\d]+$/", $item)){ //不是日期型的连加/连减/带区号电话号码数据
return '="'.$item.'"';
}else{
return $item;
}
}
}
}
//清空缓冲区
if (ob_get_level() !== 0 && @ob_end_clean() === FALSE)@ob_clean();
//输出headers
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="文件名.csv"');
header('Expires: 0');
header('Content-Transfer-Encoding: binary');
//header('Content-Length: '.$filesize);
header('Cache-Control: private, no-transform, no-store, must-revalidate');
$s='';
//输出表头
foreach($fields as $k=>$v){
$s .= format_export_string($v) . ',';
}
$s .= "\n";
echo utf82gbk($s);
ob_start();
foreach($data as $row){
foreach($fields as $k=>$v){
$field_value=$row[$k];
switch($k){ //根据字段判断数据类型是否需要转换
case 'mobile':
case 'createtime':
case 'id':
echo $field_value,',';
break;
default:
echo format_export_string($field_value),',';
}
}
echo "\n";
}
//获取缓冲区内容并转为gbk编码
$str = utf82gbk(ob_get_contents());
//清空缓冲区
ob_clean();
//重新输出转码后的内容
echo $str;
//发送至浏览器
ob_flush();
flush();
windows IIS中php增加mssql数据库支持
第一步:https://pecl.php.net/package/sqlsrv
在 changelog 中查看 php版本对应的 sqlsrv版本
第二步:下载对应 sqlsrv版本的 DLL,解压到php ext目录,修改 php.ini,
增加 extension=php_sqlsrv.dll
第三步:在 changelog 中查看所需要的 MS ODBC Driver 版本,并到给出的地址下载。
如:下载 Microsoft ODBC Driver 17 for SQL Server (x64)
下载后文件名为 msodbcsql.msi,安装并重启iis
就可以在php中使用 sqlsrv 驱动连接 mssql 数据库了
https://learn.microsoft.com/zh-cn/sql/connect/odbc/download-odbc-driver-for-sql-server
php随机生成有效的公网ipv4地址
//随机生成有效的公网ipv4地址
function generateRandomPublicIPv4() {
// 排除的IP范围(局域网、保留地址等)
$excludedRanges = [
['0.0.0.0', '0.255.255.255'], // 当前网络
['10.0.0.0', '10.255.255.255'], // 私有网络
['100.64.0.0', '100.127.255.255'], // Carrier-grade NAT
['127.0.0.0', '127.255.255.255'], // 环回地址
['169.254.0.0', '169.254.255.255'], // 链路本地
['172.16.0.0', '172.31.255.255'], // 私有网络
['192.0.0.0', '192.0.0.255'], // IETF协议分配
['192.0.2.0', '192.0.2.255'], // TEST-NET-1
['192.88.99.0', '192.88.99.255'], // 6to4中继
['192.168.0.0', '192.168.255.255'], // 私有网络
['198.18.0.0', '198.19.255.255'], // 网络基准测试
['198.51.100.0', '198.51.100.255'], // TEST-NET-2
['203.0.113.0', '203.0.113.255'], // TEST-NET-3
['224.0.0.0', '239.255.255.255'], // 组播地址
['240.0.0.0', '255.255.255.254'], // 保留地址
['255.255.255.255', '255.255.255.255'] // 广播地址
];
foreach($excludedRanges as &$row){
$row[0]=ip2long($row[0]);
$row[1]=ip2long($row[1]);
}
// 生成随机IP直到找到有效的公网IP
do {
// 生成随机IP
$ipLong = mt_rand(ip2long('1.0.0.0'), ip2long('223.255.255.255'));
$ip = long2ip($ipLong);
$isValid = true;
// 检查是否在排除范围内
foreach ($excludedRanges as $range) {
list($start,$end)=$range;
if ($ipLong >= $start && $ipLong <= $end) {
$isValid = false;
break;
}
}
// 额外检查:排除以0或255结尾的地址(通常有问题)
$parts = explode('.', $ip);
if ($parts[3] == 0 || $parts[3] == 255) {
$isValid = false;
}
} while (!$isValid);
return $ip;
}
php登录后台时一直提示验证码错误
查日志发现是新部署的业务 php/temp 目录没有写入权限
Session: Configured save path 'D:\php\temp' is not writable by the PHP process
Severity: Warning --> session_start(): Failed to initialize storage module: user (path: D:\php\temp\) D:\webroot\system\Session.php 143
PHP按目标比例和尺寸缩小并裁切图片
/**
* 按目标比例和尺寸缩小并裁切图片,如果原图尺寸小于目标尺寸,则只按比例裁切
* @param $img_name 原图片名称(不是路径)
* @param $width 目标图片宽度,如果原图宽度不等于目标宽度,则原图按目标比例缩放后再裁切
* @param $width 目标图片高度
*/
function img_convert_do($img_name, $width, $height){
$old_img=FCPATH.'photo/'.$img_name;
$new_img=FCPATH.'photo2/'.$img_name;
$size_arr = @getimagesize($old_img);
if(is_array($size_arr)){
$w = $size_arr[0];
$h= $size_arr[1];
}else{
exit('图片尺寸获取失败:'.$img_name);
}
if($w/$h < $width/$height){
$h=ceil($w*$height/$width);
}else if($w/$h > $width/$height){
$w=ceil($width*$h/$height);
}else{ //比例一致,直接复制
return copy($old_img,$new_img);
}
if($w<$width){
$width=$w;
$height=$h;
}
//新建真彩色图像
$im = imagecreatetruecolor($width, $height);
//为图像分配颜色
//$color = imagecolorallocate($im, 255,255,255);
//从指定坐标开始填充颜色
//imagefill($im, 0,0, $color);
//从字符串的图像流中新建图像,可以自动识别文件类型,但是比 imagecreatefromjpeg 等多消耗内存
$source = imagecreatefromstring(file_get_contents($old_img));
/*
从 x、y 坐标 src_x、src_y 开始,将 src_image 的一部分复制到 dst_image 上,
宽度为 src_width,高度为 src_height。定义的部分将被复制到 x,y 坐标 dst_x 和 dst_y 上。
imagecopy(
GdImage $dst_image,
GdImage $src_image,
int $dst_x,
int $dst_y,
int $src_x,
int $src_y,
int $src_width,
int $src_height
): bool
从 src_image 中取出一个宽度为 src_width 高度为 src_height 的矩形区域,
在位置(src_x、src_y)
并将其放置在 dst_image 中宽度为 dst_width 高度为 dst_height 的矩形区域中,
位置为(dst_x、dst_y)。
imagecopyresampled(
GdImage $dst_image,
GdImage $src_image,
int $dst_x,
int $dst_y,
int $src_x,
int $src_y,
int $dst_width,
int $dst_height,
int $src_width,
int $src_height
): bool
输出图象到浏览器或文件
image 由图象创建函数(例如imagecreatetruecolor())返回的 GdImage 对象。
file 文件保存的路径或者已打开的流资源(此方法返回后自动关闭该流资源),如果未设置或为 null,将会直接输出原始图象流。
quality 为可选项,范围从 0(最差质量,文件最小)到 100(最佳质量,文件最大)。默认值(-1)使用 IJG 默认的质量值(大约 75)。
imagejpeg(GdImage $image, resource|string|null $file = null, int $quality = -1): bool
*/
//执行剪裁(高质量重采样)
imagecopyresampled($im, $source, 0,0, 0,0, $width,$height, $w,$h);
imagedestroy($source);
//保存到文件
imagejpeg($im, $new_img, 90);
imagedestroy($im);
}
PHP 用 TrueType 字体向图像写入文本
/**
用 TrueType 字体向图像写入文本
image 由图象创建函数(例如imagecreatetruecolor())返回的 GdImage 对象。
size 字体的尺寸,单位:点(磅)。
angle 角度制表示的角度,0 度为从左向右读的文本。较高数值表示逆时针旋转。例如 90 度表示从下向上读的文本。
x 由 x,y 所表示的坐标定义了第一个字符的基本点(大概是字符的左下角)。这和 imagestring() 不同,其中 x,y 定义了第一个字符的左上角。例如“top left”为 0, 0。
Y 坐标。它设定了字体基线的位置,不是字符的最底端。
color 颜色索引。使用负的颜色索引值具有关闭防锯齿的效果。见 imagecolorallocate()。
fontfile 想要使用的 TrueType 字体的路径。
imagettftext(
GdImage $image,
float $size,
float $angle,
int $x,
int $y,
int $color,
string $font_filename,
string $text,
array $options = []
): array|false
*/
// 创建图像
$im = imagecreatetruecolor(300,50);
// 创建一些颜色
$white = imagecolorallocate($im, 255, 255, 255);
$grey = imagecolorallocate($im, 128, 128, 128);
$black = imagecolorallocate($im, 0, 0, 0);
imagefill($im, 0,0, $white);
// 要绘制的文本
$text = '用 TrueType 字体向图像写入文本';
// 用自己的字体路径替换路径
$font = 'ttf字体文件路径';
// 给文本添加一些阴影
imagettftext($im, 20, 0, 11, 31, $grey, $font, $text);
// 添加文本
imagettftext($im, 20, 0, 10, 30, $black, $font, $text);
// 设置 content-type
header('Content-Type: image/png');
// 与 imagejpeg() 相比,使用 imagepng() 可产生更清晰的文本
imagepng($im);
imagedestroy($im);
PHP getimagesize函数和image_type_to_extension函数
获取图片尺寸
getimagesize($image_path)
Array(
[0] => 256 //宽
[1] => 256 //高
[2] => 3 //IMAGETYPE常量,代表某种图片类型
[3] => width="256" height="256"
[bits] => 8
[mime] => image/png
)
根据 getimagesize() 返回的 IMAGETYPE常量 获取图片类型(扩展名)
image_type_to_extension(IMAGETYPE常量)
没有匹配结果时返回 false
1: .gif 2: .jpeg 3: .png 4: .swf 5: .psd 6: .bmp 7: .tiff 8: .tiff 9: .jpc 10: .jp2 11: .jpx 12: .jb2 13: .swf 14: .iff 15: .bmp 16: .xbm 17: .ico 18: .webp
PHP try...catch无效的原因及解决办法
来源:百度文心一言
在PHP中,try-catch块主要用于捕获和处理异常(Exceptions),而不是用于捕获和处理警告(Warnings)或通知(Notices)。警告和通知是PHP的错误报告机制的一部分,它们指示代码中存在潜在的问题,但通常不会阻止脚本的执行。
如果你的PHP代码中的try-catch块看起来没有按预期工作,并且直接显示了警告(Warning),这通常意味着:
1. 抛出的不是异常:你的代码可能在try块中产生了警告,而不是抛出了一个异常。警告不会自动被catch块捕获。
2. 异常未被正确抛出:如果你预期某个函数或操作会抛出异常,但实际上它没有抛出(可能因为某些条件未满足),那么catch块也不会捕获任何内容。
解决方案
1. 检查错误类型:
确保在try块中发生的是异常(Exception)而不是警告(Warning)或通知(Notice)。
如果你想处理警告或通知,你可能需要调整PHP的错误报告级别,或者使用其他机制(如错误处理函数set_error_handler())来捕获这些错误。
2. 正确抛出异常:
确保在try块中的代码在遇到问题时能够抛出异常。
如果你的代码依赖于第三方库或框架中的函数来抛出异常,请确保该函数在失败时确实会抛出异常。
3. 使用错误处理函数:
如果需要捕获警告或通知,你可以使用set_error_handler()函数来设置一个自定义的错误处理函数。这个函数可以捕获错误,并可以根据需要抛出异常。
set_error_handler(function($severity, $message, $file, $line) {
if (!(error_reporting() & $severity)){
// This error code is not included in error_reporting
return;
}
throw new ErrorException($message, 0, $severity, $file, $line);
});
$arr=array('a');
try{
trim($arr);
}catch(Exception $e) {
echo var_export($e,true);
echo $e->getMessage(), $e->getFile();
}
4. 检查PHP错误报告设置:确保你的PHP配置(php.ini)或运行时配置中的错误报告设置符合你的需求。你可以通过error_reporting()函数来动态调整错误报告级别。
