老系统维护实录:用 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

相关推荐
两个人的幸福9 天前
Windows 桌面应用自研 PHP 队列(下):完整代码与六大工程化优化
php
BingoGo11 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack11 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
用户30745969820712 天前
PHP 扩展——从入门到理解
php
鹏仔先生13 天前
拷贝漫画APP下载页PHP程序,后台带免费AI写作
php
云水一下13 天前
从零开始学 PHP 系列(一):PHP 的前世今生与开发环境搭建
开发语言·php
xingpanvip13 天前
星盘接口开发文档:本命盘接口指南
android·开发语言·css·php·lua
酉鬼女又兒13 天前
零基础入门计算机网络运输层:端到端通信核心作用、端口号分类规则、复用分用工作机制及UDP与TCP协议全方位对比详解
网络·网络协议·tcp/ip·计算机网络·考研·udp·php
dog25013 天前
不要再继续优化 TCP
网络协议·tcp/ip·php
Channing Lewis13 天前
PHP 解析 Excel 的那些坑:一次“行号错位”引发的数据丢失
开发语言·php·excel