疯狂的打印机小票

 费德  2017/07/17 22:02  990 次

WechatIMG35.jpeg

到公司实习接到的第一个任务,是实现打印一个如上图的小票。

看起来简单,却足足坑了我将近一周,光测试打印效果就足足花了三捆的打印纸。

这里的难点主要有两个:

  • 商品名称、数量和单价都要为固定的宽度

  • 商品名称需要超过折行,不能显示省略号

php处理字符串比较特殊,中文是占3个字节,而非中文则是占1个字节,并且中文的宽度是非中文的2倍左右。

查找了下相关的文档,找到了以下函数:
str_len:获取字符串的字节数
mb_str_len:获取字符串的字符数
str_pad:填充字符到指定长度

首先解决第一个问题,因为对于字符串中文比较另类,所以我们需要先找出一个字符串里有几个中文,一种思路是使用正则表达式,但是众所周知正则的性能比较低,在生产环境中应该尽量避免使用,转而可以使用如下的方式:(多出来的字节数都是中文惹的祸)

<?php
$str = "这是中文测试aaaaa";
echo (strlen($str)-mb_strlen($str))/2;

输出结果为:6(符合预期)

然后,再看下面这组数据:

  • 厉害了啊啊

  • 米饭50g

我们的目标是要把这两行都拓展为宽度为20的字符串。
在使用str_pad这个函数拓展字符串的时候,它是会把一个中文当做3个字节来处理的,也就是说如果我们要扩展到20的宽度,中文就占了3个单位,但实际上它只有2个单位那么宽,所以我们需要在拓展的时候,在目标宽度基础上再加上中文字符数,以抵消这种损失。

<?php
echo mb_str_pad("厉害了啊啊",20).";";
echo "\n";
echo mb_str_pad("米饭50g",20).";";

function mb_str_pad( $input, $pad_length, $pad_string = '_', $pad_type = STR_PAD_RIGHT)
{
   $diff = strlen( $input ) - mb_strlen( $input );
   return str_pad( $input, $pad_length + $diff/2, $pad_string, $pad_type );
}

效果如图:
WX20170717-231743@2x.png

关于第二个难点,可以使用mb_substr对字符串进行截取,比如你最大允许它的宽度为20,那就10个10个的进行截取,然后换行就可以啦。

WechatIMG37.jpeg

 作者:费德

少年费德的奇幻漂流

本博客如无特殊说明皆为原创,转载请注明来源:疯狂的打印机小票

添加新评论