老系统维护实录:用 PHP 正则 + CSS 绝对定位,优雅搞定面单打印“缝隙插针”需求

老系统维护实录:用 PHP 正则 + CSS 绝对定位,优雅搞定面单打印"缝隙插针"需求

大家好,我是"世界上最好的语言"的使用者------一名 PHPer。

最近在维护公司内部的一个 WMS(仓储管理系统)时,接到了一个让人头秃的需求。业务方要求在现有的商品标签(面单)上,增加一个"定制文案"的展示。

听起来很简单对吧?但在十年前写的老系统里,这简直是灾难。今天分享一下我是如何在不动用 DOM 解析库的情况下,用 PHP 原生能力解决这个问题的。

😱 业务场景与痛点

现有的面单打印逻辑非常古老,模版不是像现在的 Blade 或 Smarty 那样渲染的,而是直接在后端拼接了一大坨带有 style 内联样式的 HTML 字符串,存放在数据库里,取出来后直接吐给前端打印组件。

需求具体是这样的:

  1. 位置刁钻:要在"平台SKC编号"和"平台海外仓多属性"这两个字段中间,插入一个新的字段。
  2. 空间有限 :这个新字段最多只能展示 6 个字符的宽度,超长必须截断,不能换行。
  3. 不能动老结构 :原有的 HTML 结构是通过绝对定位(position: absolute)排版的,坐标写死在 style 里的,牵一发而动全身。

面对着那一坨杂乱的 HTML 字符串,使用 DOMDocumentSimpleHTMLDom 解析不仅慢,还容易因为 HTML 标签不规范导致报错。这时候,PHP 强大的正则处理能力就派上用场了。

🛠️ 解决方案:PHP 正则手术刀

我的思路是:找到"SKC编号"的闭合 </div> 标签,在它后面无缝拼接我们要插入的新 div

1. 正则表达式的构建

最关键的一步是如何精准定位。原有的 HTML 标签混杂着各种属性和换行符。

php 复制代码
$pattern = '/(<div[^>]*?data-title="平台SKC编号"[^>]*?>.*?<\/div>)/is';

这里有几个知识点值得分享:

  • [^>]*? :非贪婪匹配,确保我们匹配的是当前的 div 开始标签,防止跨越到下一个标签。
  • data-title="..." :利用业务特有的属性作为锚点,比用 class 靠谱,因为 class 可能会变,但业务标识一般不变。
  • /is 修饰符这是重点!
    • i:忽略大小写。
    • s让点号 . 可以匹配换行符。因为 HTML 源码中往往包含大量的换行和空格,如果不加这个修饰符,正则会直接失效。

2. CSS 布局的魔法

后端插入了 HTML 只是第一步,前端展示还得对齐。由于原有的布局是 absolute,我们新插入的元素也必须"悬浮"在指定坐标。

业务要求"最多展示6个字符",这里我用了一个 CSS 小技巧:em 单位。

  • width: 6em:大约就是 6 个字符的宽度(取决于字体大小)。
  • overflow: hidden:物理截断,防止内容撑破版面。
  • white-space: nowrap:强制不换行。
  • z-index: 99:确保新内容浮在最上层,不被背景遮挡。

3. 最终代码实现

直接上代码,干净利落:

css 复制代码
<?php
// 模拟原始 HTML 字符串(一坨乱糟糟的代码)
$str = $originalHtmlFromDb; 

// 假设这是从订单数据中获取的定制文案
$customText = "Lukas, 67"; 

// 构建要插入的 HTML 代码
// 注意 style 设置:
// 1. position: absolute; top: 4px; (与左右元素高度对齐)
// 2. left: 110px; (大致位于左侧和右侧元素中间,需要微调)
// 3. width: 6em; (限制宽度约为6个字符)
$insertHtml = sprintf(
    '<div class="dropitem" data-title="定制文案" style="position: absolute; top: 4px; left: 110px; width: 6em; height: 15px; text-align: center; overflow: hidden; white-space: nowrap; z-index: 99;">
        <span class="detail" style="font-size: 10px; line-height: 10px; font-weight: 700;">%s</span>
    </div>',
    $customText
);

// 正则替换:将捕获到的 $1 (即 SKC 编号的 div) 放回去,并在后面追加我们的新 div
$result = preg_replace(
    '/(<div[^>]*?data-title="平台SKC编号"[^>]*?>.*?<\/div>)/is', 
    '$1' . $insertHtml, 
    $str
);

// 输出或保存结果
echo $result;

💡 总结

虽然现在流行前后端分离,但在处理 ERP、WMS 这种涉及硬件打印、老旧报表系统的业务时,PHP 的字符串处理能力依然是"神"一般的存在。

通过 preg_replace 配合 /s 模式,我们可以在不动用繁重 DOM 解析库的情况下,像外科手术一样精准修改 HTML 结构。再配合一点点 CSS 的 emoverflow 技巧,完美满足了业务方"既要又要"的需求。

PHP 不死,它只是在闷声发大财(解决实际问题)。

如果你也遇到过这种老系统维护的坑,欢迎在评论区一起吐槽交流!👋


标签: #PHP #正则表达式 #后端开发 #踩坑记录 #CSS

相关推荐
p66666666681 天前
大小端存储
服务器·网络·php
未来之窗软件服务1 天前
幽冥大陆(九十二 ) 封装 PHP HTTP 请求的 —东方仙盟练气期
开发语言·http·php·仙盟创梦ide·东方仙盟
2501_941885961 天前
高并发网络IO场景中的工程思维转变与多语言实现方式随笔记录分享
开发语言·php
catchadmin1 天前
PHP 高效的标准库 SPL 全面指南
开发语言·php
xixixi777771 天前
RDMA(远程直接内存访问——允许外部设备直接访问主机的主存,绕过CPU,从而提高数据传输效率
服务器·网络·php·内存·数据中心·数据传输·rdma
Shi_haoliu1 天前
SolidTime 本地与服务器环境搭建指南(Laragon + Laravel + Vue3 + PostgreSQL)
服务器·vue.js·ai·postgresql·php·laravel
JaguarJack1 天前
PHP 8.5 管道操作符 (|>) 告别嵌套函数地狱,写出清晰的数据管道
后端·php·服务端
BingoGo1 天前
PHP 8.5 管道操作符 (|>) 告别嵌套函数地狱,写出清晰的数据管道
后端·php
fishwheel1 天前
Binary:CAPEv2安装配置
开发语言·php
fillwang1 天前
德力西DTS606电表读数采集实践(485转网络+Python)
网络·python·php