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

相关推荐
BingoGo11 小时前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack11 小时前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo1 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack1 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack2 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo2 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack3 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理4 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
QQ5110082854 天前
python+springboot+django/flask的校园资料分享系统
spring boot·python·django·flask·node.js·php
WeiXin_DZbishe4 天前
基于django在线音乐数据采集的设计与实现-计算机毕设 附源码 22647
javascript·spring boot·mysql·django·node.js·php·html5