101 lines
2.8 KiB
PHP
101 lines
2.8 KiB
PHP
<?php
|
||
|
||
namespace App\Service\common;
|
||
|
||
/**
|
||
* 媒体地址规整
|
||
*
|
||
* 老后台的约定是:入库存相对路径(/storage/xxx.jpg),出库用 asset() 拼成绝对地址;
|
||
* 而 OSS 上传拿到的本来就是绝对地址。两种值混在同一列里,读写都得判断一次。
|
||
* 这里把判断收在一处,业务 Service 只调 toPublic / toStorage。
|
||
*/
|
||
class MediaUrlService
|
||
{
|
||
private static mixed $_instance;
|
||
|
||
public static function getInstance(): null|static
|
||
{
|
||
$name = get_called_class();
|
||
if (!isset(self::$_instance[$name])) {
|
||
self::$_instance[$name] = new static();
|
||
}
|
||
return self::$_instance[$name];
|
||
}
|
||
|
||
/**
|
||
* 出库:相对路径补上站点域名,绝对地址原样返回
|
||
*/
|
||
public function toPublic(?string $path): string
|
||
{
|
||
$path = trim((string) $path);
|
||
if ($path === '') {
|
||
return '';
|
||
}
|
||
if ($this->isAbsolute($path)) {
|
||
return $path;
|
||
}
|
||
return rtrim((string) config('app.url'), '/') . '/' . ltrim($path, '/');
|
||
}
|
||
|
||
/**
|
||
* 入库:本站域名下的地址存成相对路径,避免换域名后历史数据全指向旧域名;
|
||
* 第三方 OSS 地址保持原样
|
||
*/
|
||
public function toStorage(?string $url): string
|
||
{
|
||
$url = trim((string) $url);
|
||
if ($url === '') {
|
||
return '';
|
||
}
|
||
$appUrl = rtrim((string) config('app.url'), '/');
|
||
if ($appUrl !== '' && str_starts_with($url, $appUrl)) {
|
||
return substr($url, strlen($appUrl)) ?: '';
|
||
}
|
||
return $url;
|
||
}
|
||
|
||
/**
|
||
* 批量出库,给 list 用
|
||
*/
|
||
public function publicEach(array &$rows, array $fields): void
|
||
{
|
||
foreach ($rows as &$row) {
|
||
foreach ($fields as $field) {
|
||
if (array_key_exists($field, $row)) {
|
||
$row[$field] = $this->toPublic($row[$field]);
|
||
}
|
||
}
|
||
}
|
||
unset($row);
|
||
}
|
||
|
||
/**
|
||
* 前端图片上传组件回传的是数组,取第一个;已是字符串则原样
|
||
*/
|
||
public function firstOf(mixed $value): string
|
||
{
|
||
if (is_array($value)) {
|
||
$value = $value[0] ?? '';
|
||
}
|
||
return $this->toStorage(is_string($value) ? $value : '');
|
||
}
|
||
|
||
/**
|
||
* 去掉 OSS 处理参数(?imageView2/... 或 ?watermark/...),用于素材库按 path 做引用匹配
|
||
*/
|
||
public function stripProcessParams(?string $url): string
|
||
{
|
||
$url = trim((string) $url);
|
||
if ($url === '') {
|
||
return '';
|
||
}
|
||
$pos = strpos($url, '?');
|
||
return $pos === false ? $url : substr($url, 0, $pos);
|
||
}
|
||
|
||
private function isAbsolute(string $path): bool
|
||
{
|
||
return (bool) preg_match('#^(https?:)?//#i', $path);
|
||
}
|
||
}
|