我们文章图片图片路径一般是存放绝对路径的,放相对路径也行不过处理麻烦还要加多次处理浪费性能。
绝对路径的弊端就是服务器域名替换或者存放的图片路径的目录名称/目录路径变化就会导致图片加载不出来。
而且文章多的时候不能手动处理的吧,所以最近写了一个批量修改图片文章路径的方法。
Tips:数据量多可以启动队列或者分批定时任务处理一定数量
思路是先获取html标签<img>的src属性然后修改前缀的路径。
使用到一些字符串替换截取方法
-
preg_match_all()
-
strstr()
-
preg_replace()
-
str_replace()
·–· int preg_match_all (pattern , subject ,matches,flags,offset); ·–·
| pattern | 要搜索的模式,字符串形式。 |
| subject | 输入字符串。 |
| matches | 多维数组,作为输出参数输出所有匹配结果, 数组排序通过flags指定。 |
| flags | 数组结果排序,下文介绍。 |
| offset | 通常, 查找时从目标字符串的开始位置开始。(单位为字节) |
flags
- PREG_PATTERN_ORDER:结果排序为$matches[0]保存完整模式的所有匹配, $matches[1] 保存第一个子组的所有匹配,以此类推。
- REG_SET_ORDER::结果排序为$matches[0]包含第一次匹配得到的所有匹配(包含子组), $matches[1]是包含第二次匹配到的所有匹配(包含子组)的数组,以此类推。
- PREG_OFFSET_CAPTURE: 如果这个标记被传递,每个发现的匹配返回时会增加它相对目标字符串的偏移量。
- 注意:PREG_PATTERN_ORDER 和 PREG_SET_ORDER 不能同时使用,如果没有指定排序的标记,则默认为 PREG_PATTERN_ORDER
返回值
preg_match_all():返回完整匹配次数有可能为0,如果发生错误则返回false
preg_match_all使用
text
<?php
/**
* @annotations
* $str要截取的字符串
* $img_src执行成功后输出的字符串
*/
$str="<p style="color: #ff7f24;">·靠右和向下(调了opacity属性)·</p>
<p style="color: #ff7f24;"><img src="https://www.lemonsuger.com/admin-api/infra/file/29/get/blog/legacy/image/20210824/290cd0917b03d10cc4fba527faa3c01d.jpg" alt="" width="100%" height="100%" /></p>
<div class="ngv_title">三.hsla模式</div>";
preg_match_all("/<img (href|src)=([\"|']?)([^\"'>]+)/i", $str, $img_src, PREG_PATTERN_ORDER);
·输出·
text
array:4 [
0 => array:1 [
0 => "<img src="https://www.lemonsuger.com/admin-api/infra/file/29/get/blog/legacy/image/20210824/290cd0917b03d10cc4fba527faa3c01d.jpg"
]
1 => array:1 [
0 => "src"
]
2 => array:1 [
0 => """
]
3 => array:1 [
0 => "https://www.lemonsuger.com/admin-api/infra/file/29/get/blog/legacy/image/20210824/290cd0917b03d10cc4fba527faa3c01d.jpg"
]
]
·这里一般我们只用到img的src属性所以拿数据**$img[0][3]**就行了·
·–· strstr(string,search,before_search) ·–·
| string | 必需。规定被搜索的字符串。 |
| search | 必需。规定所搜索的字符串。 如果此参数是数字,则搜索匹配此数字对应的 ASCII 值的字符。 |
| before_search | 可选。默认值为 “false” 的布尔值。 如果设置为 “true”,它将返回 search 参数第一次出现之前的字符串部分。 |
strstr()使用
text
<?php
echo strstr("I love Shanghai!","Shanghai"); //输出为Shanghai!
?>
·–·preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] ) ·–·
| pattern | 要搜索的模式,可以是字符串或一个字符串数组。 |
| replacement | 用于替换的字符串或字符串数组。 |
| subject | 要搜索替换的目标字符串或字符串数组。 |
| limit | 可选,对于每个模式用于每个 subject 字符串的最大可替换次数。 默认是-1(无限制)。 |
| count | 可选,为替换执行的次数。 |
正则就不说网上一查一堆
preg_replace()使用
text
<?php
$str="https://www.lemonsuger.com/storage/20210824/290cd0917b03d10cc4fba527faa3c01d.jpg"
$initial_str = '/storage';
$new_header = 'https://www.lemonsuger.com/storage/image';
$new_img_src =$new_header . '/' . preg_replace('/^\/storage\//', '', $str, strstr($str, $initial_str));
//strstr截取到https://www.lemonsuger.com/storage/20210824/290cd0917b03d10cc4fba527faa3c01d.jpg这个后面再去除/storage拼上需要的路径
//给链接/storage目录添加https://www.lemonsuger.com/storage/image暂时想到这个办法应该还有其他大神想到的办法的
输出
text
echo preg_replace('/^\/storage\//', '', $str, strstr($str, $initial_str)) //输出为"/20210824/290cd0917b03d10cc4fba527faa3c01d.jpg"
//这里只要不会改变的路径
·–·str_replace(find,replace,string,count)·–·
| find | 必需。规定要查找的值。 |
| replace | 必需。规定替换 find 中的值的值。 |
| string | 必需。规定被搜索的字符串。 |
| count | 可选。一个变量,对替换数进行计数。 |
text
<?php
$str="https://www.lemonsuger.com/storage/20210824/290cd0917b03d10cc4fba527faa3c01d.jpg"
echo $new_str = str_replace("/", '\/', $img_src[3][0]);
输出
text
"https:\/\/www.lemonsuger.com\/storage\/20210824\/290cd0917b03d10cc4fba527faa3c01d.jpg"
正片了:文章内容图片路径修改代码(Laravel为例)
text
/**
* @annotations 文章内容路径修改
* @return JsonResponse
*/
public function imageContent()
{
$table = new Article();
$field = 'content';
$info = $table::query()->pluck($field)->toArray();
$data = $table::query()->pluck('article_id')->toArray();;
$initial_str = '/storage';
$new_header = 'https://www.lemonsuger.com/storage/image';
DB::beginTransaction();
try {
foreach ($data as $k => $v) {
//获取href和src标签 标签属性
preg_match_all("/<img (href|src)=([\"|']?)([^\"'>]+)/i", $info[$k], $img_src, PREG_PATTERN_ORDER);
//判断有img标签 无就不修改
if (!empty($img_src[3][0])) {
//匹配不需要修改的地方
$new_img_src = $new_header . '/' . preg_replace('/^\/storage\//', '', strstr($img_src[3][0], $initial_str));
$new_str = str_replace("/", '\/', $img_src[3][0]);
$table::query()->where('article_id', $v)->update([$field => preg_replace("/$new_str/", $new_img_src, $info[$k])]);
}
}
DB::commit();
return $this->success($data);
} catch (\Throwable $e) {
DB::rollBack();
return $this->error('迁移失败', 500, $e->getMessage());
}
}