問題描述
我們希望打印到連接 apache 運行的 POS 打印機.由于應用程序的設計和部署,打印應該從服務器完成(它應該檢測訂單并發送到不同的打印機和不同的打印格式......賬單,廚房訂單等等......).出于這個原因和其他原因(例如從 iPad 訪問應用程序),我們放棄了 QZ-Print 小程序等選項,需要直接在服務器端打印.
我們搜索了很多,發現有一個叫php-printer的擴展,但是好像已經過時了,只能在WINdows下運行.
我們遵循以下代碼:(http://mocopat.wordpress.com/2012/01/18/php-direct-printing-printer-dot-matrix-lx-300/)
$tmpdir = sys_get_temp_dir();# ambil direktori 臨時 untuk simpan 文件.$file = tempnam($tmpdir, 'ctk');# nama 文件臨時 yang akan dicetak$handle = fopen($file, 'w');$condensed = Chr(27) .鉻(33).鉻(4);$bold1 = Chr(27) .鉻(69);$bold0 = Chr(27) .鉻(70);$initialized = chr(27).chr(64);$condensed1 = chr(15);$condensed0 = chr(18);$corte = Chr(27) .鉻(109);$Data = $initialized;$數據 .= $condensed1;$Data .= "==========================
";$Data .= "| ".$bold1."OFIDZ MAJEZTY".$bold0." |
";$Data .= "==========================
";$Data .= "Ofidz Majezty 來了
";$Data .= "我們愛 PHP 印度尼西亞
";$Data .= "我們愛 PHP 印度尼西亞
";$Data .= "我們愛 PHP 印度尼西亞
";$Data .= "我們愛 PHP 印度尼西亞
";$Data .= "我們愛 PHP 印度尼西亞
";$Data .= "----------------------------------------
";$數據 .= $corte;fwrite($handle, $Data);fclose($handle);copy($file, "http://localhost/KoTickets");#Lakukan cetak取消鏈接($文件);
它可以工作,但是這會發送純文本,我們需要發送圖像(徽標),并格式化更可愛的帳單.我們嘗試以相同的方式創建 PDF 并發送"到打印機,但只是打印空白.
我找到了一個可以使用網絡打印機的庫(github 上的 escpos-php),但我們也需要使用 USB 打印機,以避免我們的客戶更換硬件.
如何實現這一目標的一些想法?
提前致謝.
escpos-php 的作者在這里.>
如果您的打印機確實支持 ESC/POS(大多數熱敏收據打印機似乎使用它的某些子集),那么我認為該驅動程序將適應您的用例:USB 或網絡打印、徽標、某些格式.其中一些是最近添加的.
USB 打印
escpos-php 打印到文件指針.在 Linux 上,您可以使用 usblp
驅動程序使 USB 打印機作為 aa 文件可見,然后只需 fopen()
它(USB 收據示例,關于在 Linux 上安裝 USB 打印機的博文).
因此,在 USB 打印機上打印Hello world"與在網絡打印機上打印僅略有不同:
text("Hello World!
");$打印機 ->切();$打印機 ->關閉();
或者,更像是您當前成功使用的代碼,您可以寫入臨時文件并復制它:
text("Hello World!
");$打印機 ->切();$打印機 ->關閉();/* 將它復制到打印機 */copy($file, "http://localhost/KoTickets");取消鏈接($文件);
因此,在您的 POS 系統中,您需要一個函數,該函數根據您的客戶配置和首選目的地返回文件指針.收據打印機響應很快,但如果您有幾臺 iPad 下訂單,您應該使用文件鎖將操作包裝到每臺打印機 (flock()) 以避免與并發相關的麻煩.
另請注意,Windows 上的 USB 支持未經測試.
標志 &格式化
一旦您確定了如何與打印機通信,您就可以使用全套格式和圖像命令.
可以像這樣從 PNG 文件打印徽標:
使用 Mike42EscposEscposImage;$logo = EscposImage::load("foo.png");$打印機 ->圖形($標志);
對于格式化,README.md 和下面的示例應該可以幫助您開始了.對于大多數收據,您只需要:
selectPrintMode()
改變字體大小.setEmphasis()
切換粗體.setJustification()
將某些文本或圖像左對齊或居中.cut()
在每次收據之后.
我還建議您在當前使用的示例中繪制這樣的框:
==========||==========
您可以使用 IBM 代碼頁 437 中的字符,這些字符專為繪制許多支持的框而設計打印機 - 只在輸出中包含字符 0xB3 到 0xDA.它們并不完美,但看起來少了很多文本"-y.
$box = "xda".str_repeat("xc4", 10)."xbf
";$box .= "xb3".str_repeat(" ", 10)."xb3
";$box .= "xc0".str_repeat("xc4", 10)."xd9
";$打印機 ->textRaw($box);
完整示例
以下示例現在也包含司機.我認為它看起來像一個相當典型的商店收據,格式方面,并且可以很容易地適應您的廚房場景.
掃描輸出:
生成它的PHP源代碼:
setJustification(打印機::JUSTIFY_CENTER);$打印機 ->圖形($標志);/* 店鋪名稱 */$打印機 ->選擇打印模式(打印機:: MODE_DOUBLE_WIDTH);$打印機 ->text("ExampleMart Ltd.
");$打印機 ->選擇打印模式();$打印機 ->text("42號店.
");$打印機 ->喂養();/* 收據標題 */$打印機 ->設置重點(真);$打印機 ->text("銷售發票
");$打印機 ->設置重點(假);/* 項目 */$打印機 ->setJustification(打印機::JUSTIFY_LEFT);$打印機 ->設置重點(真);$打印機 ->文本(新項目('','$'));$打印機 ->設置重點(假);foreach ($items as $item) {$打印機 ->文本($項目);}$打印機 ->設置重點(真);$打印機 ->文本($小計);$打印機 ->設置重點(假);$打印機 ->喂養();/* 稅收和總額 */$打印機 ->文本($稅);$打印機 ->選擇打印模式(打印機:: MODE_DOUBLE_WIDTH);$打印機 ->文本($總計);$打印機 ->選擇打印模式();/*頁腳*/$打印機 ->飼料(2);$打印機 ->setJustification(打印機::JUSTIFY_CENTER);$打印機 ->text("感謝您在 ExampleMart 購物
");$打印機 ->text("交易時間請訪問example.com
");$打印機 ->飼料(2);$打印機 ->文本($日期.
");/* 剪下收據并打開錢箱 */$打印機 ->切();$打印機 ->脈沖();$打印機 ->關閉();/* 一個包裝器來組織項目名稱 &價格列*/類項目{私人 $name;私人$價格;私人 $dollarSign;公共函數 __construct($name = '', $price = '', $dollarSign = false){$this ->名稱 = $name;$this ->價格= $價格;$this ->美元符號 = $dollarSign;}公共函數 __toString(){$rightCols = 10;$leftCols = 38;如果 ($this -> 美元符號) {$leftCols = $leftCols/2 - $rightCols/2;}$left = str_pad($this -> name, $leftCols) ;$sign = ($this -> DollarSign ? '$' : '');$right = str_pad($sign . $this -> price, $rightCols, ' ', STR_PAD_LEFT);返回 "$left$right
";}}
We are looking to print to a POS printer connected where apache is running. Due to design of the application, and deployment, printing should be done from Server (it should detect the order and send to different printers and different formats of printing...bill, kitchen orders, and so on...). For this reason and others (like access application from an iPad for example) we discard options like QZ-Print applet and needst o print directly server side.
We searched a lot, and found that there are an extension called php-printer but seems outdated, and just works under WIndows.
We followed this code: (http://mocopat.wordpress.com/2012/01/18/php-direct-printing-printer-dot-matrix-lx-300/)
$tmpdir = sys_get_temp_dir(); # ambil direktori temporary untuk simpan file.
$file = tempnam($tmpdir, 'ctk'); # nama file temporary yang akan dicetak
$handle = fopen($file, 'w');
$condensed = Chr(27) . Chr(33) . Chr(4);
$bold1 = Chr(27) . Chr(69);
$bold0 = Chr(27) . Chr(70);
$initialized = chr(27).chr(64);
$condensed1 = chr(15);
$condensed0 = chr(18);
$corte = Chr(27) . Chr(109);
$Data = $initialized;
$Data .= $condensed1;
$Data .= "==========================
";
$Data .= "| ".$bold1."OFIDZ MAJEZTY".$bold0." |
";
$Data .= "==========================
";
$Data .= "Ofidz Majezty is here
";
$Data .= "We Love PHP Indonesia
";
$Data .= "We Love PHP Indonesia
";
$Data .= "We Love PHP Indonesia
";
$Data .= "We Love PHP Indonesia
";
$Data .= "We Love PHP Indonesia
";
$Data .= "--------------------------
";
$Data .= $corte;
fwrite($handle, $Data);
fclose($handle);
copy($file, "http://localhost/KoTickets"); # Lakukan cetak
unlink($file);
And it works, but this sends plain text, and we need to send image (logo), and format a more cute bill. We tried creating a PDF and "sending" to the printer in the same way, but just prints blank.
I found a library to work with network printers (escpos-php on github), but we need to work with USB printers too, to avoid our customers to change hardware.
Some ideas how to achieve this?
Thanks in advance.
Author of escpos-php here.
If your printers do support ESC/POS (most thermal receipt printers seem to use some sub-set of it), then I think the driver will accommodate your use case: USB or network printing, logo, some formatting. Some of these are quite recent additions.
USB printing
escpos-php prints to a file pointer. On Linux, you can make the USB printer visible as a a file using the usblp
driver, and then just fopen()
it (USB receipt example, blog post about installing a USB printer on Linux).
So printing "Hello world" on a USB printer is only slightly different to printing to a networked printer:
<?php
require __DIR__ . '/vendor/autoload.php';
use Mike42EscposPrintConnectorsFilePrintConnector;
use Mike42EscposPrinter;
$connector = new FilePrintConnector("/dev/usb/lp0");
$printer = new Printer($connector);
$printer -> text("Hello World!
");
$printer -> cut();
$printer -> close();
Or, more like the code you are currently using successfully, you could write to a temp file and copy it:
<?php
require __DIR__ . '/vendor/autoload.php';
use Mike42EscposPrintConnectorsFilePrintConnector;
use Mike42EscposPrinter;
/* Open file */
$tmpdir = sys_get_temp_dir();
$file = tempnam($tmpdir, 'ctk');
/* Do some printing */
$connector = new FilePrintConnector($file);
$printer = new Printer($connector);
$printer -> text("Hello World!
");
$printer -> cut();
$printer -> close();
/* Copy it over to the printer */
copy($file, "http://localhost/KoTickets");
unlink($file);
So in your POS system, you would need a function which returns a file pointer based on your customer configuration and preferred destination. Receipt printers respond quite quickly, but if you have a few iPads making orders, you should wrap operations to each printer with a file lock (flock()) to avoid concurrency-related trouble.
Also note that USB support on Windows is un-tested.
Logo & Formatting
Once you have figured out how you plan to talk to the printer, you can use the full suite of formatting and image commands.
A logo can be printed from a PNG file like so:
use Mike42EscposEscposImage;
$logo = EscposImage::load("foo.png");
$printer -> graphics($logo);
And for formatting, the README.md and the example below should get you started. For most receipts, you only really need:
selectPrintMode()
to alter font sizes.setEmphasis()
to toggle bold.setJustification()
to left-align or center some text or images.cut()
after each receipt.
I would also suggest that where you are currently using an example that draws boxes like this:
=========
| |
=========
You could make use of the characters in IBM Code page 437 which are designed for drawing boxes that are supported by many printers- just include characters 0xB3 to 0xDA in the output. They aren't perfect, but it looks a lot less "text"-y.
$box = "xda".str_repeat("xc4", 10)."xbf
";
$box .= "xb3".str_repeat(" ", 10)."xb3
";
$box .= "xc0".str_repeat("xc4", 10)."xd9
";
$printer -> textRaw($box);
Full example
The below example is also now included with the driver. I think it looks like a fairly typical store receipt, formatting-wise, and could be easily adapted to your kitchen scenario.
Scanned output:
PHP source code to generate it:
<?php
require __DIR__ . '/vendor/autoload.php';
use Mike42EscposPrinter;
use Mike42EscposEscposImage;
use Mike42EscposPrintConnectorsFilePrintConnector;
/* Open the printer; this will change depending on how it is connected */
$connector = new FilePrintConnector("/dev/usb/lp0");
$printer = new Printer($connector);
/* Information for the receipt */
$items = array(
new item("Example item #1", "4.00"),
new item("Another thing", "3.50"),
new item("Something else", "1.00"),
new item("A final item", "4.45"),
);
$subtotal = new item('Subtotal', '12.95');
$tax = new item('A local tax', '1.30');
$total = new item('Total', '14.25', true);
/* Date is kept the same for testing */
// $date = date('l jS of F Y h:i:s A');
$date = "Monday 6th of April 2015 02:56:25 PM";
/* Start the printer */
$logo = EscposImage::load("resources/escpos-php.png", false);
$printer = new Printer($connector);
/* Print top logo */
$printer -> setJustification(Printer::JUSTIFY_CENTER);
$printer -> graphics($logo);
/* Name of shop */
$printer -> selectPrintMode(Printer::MODE_DOUBLE_WIDTH);
$printer -> text("ExampleMart Ltd.
");
$printer -> selectPrintMode();
$printer -> text("Shop No. 42.
");
$printer -> feed();
/* Title of receipt */
$printer -> setEmphasis(true);
$printer -> text("SALES INVOICE
");
$printer -> setEmphasis(false);
/* Items */
$printer -> setJustification(Printer::JUSTIFY_LEFT);
$printer -> setEmphasis(true);
$printer -> text(new item('', '$'));
$printer -> setEmphasis(false);
foreach ($items as $item) {
$printer -> text($item);
}
$printer -> setEmphasis(true);
$printer -> text($subtotal);
$printer -> setEmphasis(false);
$printer -> feed();
/* Tax and total */
$printer -> text($tax);
$printer -> selectPrintMode(Printer::MODE_DOUBLE_WIDTH);
$printer -> text($total);
$printer -> selectPrintMode();
/* Footer */
$printer -> feed(2);
$printer -> setJustification(Printer::JUSTIFY_CENTER);
$printer -> text("Thank you for shopping at ExampleMart
");
$printer -> text("For trading hours, please visit example.com
");
$printer -> feed(2);
$printer -> text($date . "
");
/* Cut the receipt and open the cash drawer */
$printer -> cut();
$printer -> pulse();
$printer -> close();
/* A wrapper to do organise item names & prices into columns */
class item
{
private $name;
private $price;
private $dollarSign;
public function __construct($name = '', $price = '', $dollarSign = false)
{
$this -> name = $name;
$this -> price = $price;
$this -> dollarSign = $dollarSign;
}
public function __toString()
{
$rightCols = 10;
$leftCols = 38;
if ($this -> dollarSign) {
$leftCols = $leftCols / 2 - $rightCols / 2;
}
$left = str_pad($this -> name, $leftCols) ;
$sign = ($this -> dollarSign ? '$ ' : '');
$right = str_pad($sign . $this -> price, $rightCols, ' ', STR_PAD_LEFT);
return "$left$right
";
}
}
這篇關于從 PHP 打印到 POS 打印機的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!