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

相关推荐
北辰当尹16 小时前
【小迪安全2023】day42 php应用&mysql架构&sql注入&跨库查询&文件读写&权限操作
mysql·安全·php
2501_9481201519 小时前
基于机器学习的网络异常检测与响应技术研究
网络·机器学习·php
郑州光合科技余经理19 小时前
技术架构:海外版外卖平台搭建全攻略
java·大数据·人工智能·后端·小程序·架构·php
2301_7679026420 小时前
第 5 章 docker网络
网络·docker·php
我不是程序员yy1 天前
防火墙与IDS/IPS:构建网络边界的“盾”与“剑”
开发语言·php
a程序小傲1 天前
米哈游Java面试被问:gRPC的HTTP/2流控制和消息分帧
java·开发语言·tcp/ip·http·面试·职场和发展·php
全栈软件开发1 天前
php图形验证码生成系统源码 支持api接口调用 提供SDK 轻量级简单易用
开发语言·php
ujainu1 天前
Flutter + OpenHarmony 图片加载:Image 组件与 BoxFit、缓存策略在 OpenHarmony 设备上的优化
开发语言·php·组件
Getgit1 天前
在 VS Code 中配置 PHP 开发环境完整指南
开发语言·vscode·php·intellij-idea·database
云游云记1 天前
php自动加载
android·php·android studio