PHP 简易云打印类实现原理与示例
当面临大量电脑终端需要共享打印资源但缺乏专用网络打印机时,基于PHP构建一个简易的云打印中间件是一种有效的解决方案。该方案利用MySQL数据库作为作业队列,将前端页面的打印请求序列化存储,随后由服务端脚本按序调度,并利用JavaScript在客户端调用浏览器的原生打印接口完成物理输出。
设计思路与目标
该打印类的核心逻辑分为“数据收集”与“任务执行”两个阶段:
- 数据收集(排队):前端或外部系统提交包含用户名、打印内容及IP地址的数据。服务器接收后,验证数据有效性并将记录插入数据库,赋予初始状态(如未打印),同时返回当前队列位置供前端反馈。
- 任务执行(打印):服务端轮询或触发查询数据库中状态为“未打印”的第一条记录。获取内容后,通过输出嵌入JavaScript代码的方式,调用客户端的
window.print()方法触发浏览器打印对话框,最后将数据库中的记录状态更新为“已打印”。
此方法主要依赖浏览器的本地打印能力,适用于Internet Explorer等对ActiveX或特定脚本兼容性较好的环境,能够解决多台设备共用一台物理打印机的排队与调度问题。
环境准备与数据库配置
在运行上述代码之前,需要确保服务器具备以下基础环境:
- PHP运行环境:需开启数据库扩展(如
mysql或建议升级后的mysqli/pdo)。 - MySQL数据库:需要一个专门的库来存储打印任务队列。
- 数据库表结构:需创建名为
print的表,字段包括:
id(INT, AUTO_INCREMENT): 唯一标识符,用于排序和状态管理。username(VARCHAR): 提交打印任务的账号。content(TEXT): 待打印的具体文本或HTML内容。ip(VARCHAR): 提交者的IP地址,便于追踪来源。state(TINYINT): 任务状态,0代表待打印,1代表已完成。priority(TINYINT): 优先级设置(本示例中固定为0)。
注意:原代码使用的是已废弃的 mysql_ 系列函数,且硬编码了数据库连接信息(localhost/root/123456/shen)。在生产环境中,请务必使用参数化查询防止SQL注入,并采用PDO或mysqli扩展,同时避免在前置脚本中暴露真实密码。
核心功能代码解析
第1步:初始化与数据收集
通过构造方法自动触发数据的采集。系统首先设定字符集为UTF-8,建立数据库连接,随即调用 collect() 方法处理POST传入的参数。
class Wprint{
private $data = array(); // 内存中的数据暂存池
public function __construct()
{
header("Content-type:text/html;charset=utf-8");
$this->link(); // 链接数据库
// 假设前端传入了 username, content, ip
$this->collect($_POST["username"], $_POST["content"], $_POST["ip"]);
$this->handle(); // 立即处理入队
}
// ... 其他方法
}
第2步:数据校验与入库队列
collect() 方法负责封装数据节点。它会先调用 check() 验证输入内容是否为空,若有效则压入 $data 数组。随后 handle() 方法遍历该数组,拼接INSERT语句写入数据库。
// 检查传人数据是否为空
private function check($string){
if(strlen($string) == 0 || $string == " "){
echo "数据收集失败,打印内容为空";
exit;
} else {
return $string;
}
}
// 处理打印代码入库
private function handle(){
foreach($this->data as $value){
// 注意:此处存在SQL注入风险,生产环境应使用预处理语句
$sql = "insert into print(username,content,ip,state,priority)
values('{$value["username"]}','{$value["content"]}',
'{$value["ip"]}','{$value["state"]}','{$value["priority"]}')";
$query = mysql_query($sql);
if($query){
// 获取刚插入记录的ID
$id = mysql_insert_id();
echo "数据收集成功,正在排队打印,排队ID为".$id;
$this->num($id); // 计算前面还有多少人
} else {
echo "数据收集失败,请3秒后再一次提交";
}
}
}
第3步:排队人数统计
num() 方法通过查询当前ID之前且状态为0的记录数量,让用户知道自己在队列中的大致位置。
private function num($id){
// 查找状态为0且ID小于当前ID的记录数
$sql = "select id from print where state=0 and id<".$id." order by id asc";
$query = mysql_query($sql);
$num = mysql_num_rows($query);
echo ",您前面还有".$num."个人在排队";
}
第4步:触发实际打印动作
这是实现“云打印”的关键步骤。Yprint() 方法查询第一条待处理任务(state=0),如果获取到内容,直接输出带有 window.print() 的 <script> 标签。当浏览器加载该响应并执行脚本时,会弹出系统的打印预览窗口,用户点击打印即完成任务。
public function Yprint(){
// 取出第一条待打印数据
$sql = "select id,content from print where state=0 order by id asc limit 1";
$query = mysql_query($sql);
$row = mysql_fetch_array($query);
if(!empty($row["content"])){
// 输出JS触发浏览器打印
echo "<script type=\"text/javascript\">\n window.print();\n </script>";
// 更新状态为已打印(1)
$id = $row["id"];
$sql = "update print set state=1 where id=".$id;
mysql_query($sql);
echo "打印处理完成";
} else {
echo $row["content"]; // 兜底显示
}
}
技术局限性与改进建议
虽然该示例演示了基本的队列与触发逻辑,但在现代开发中需注意以下问题:
- 浏览器兼容性:
window.print()在现代标准模式下通常要求页面有实际的DOM内容展示,而不仅仅是纯JS输出。原方案依赖特定的浏览器行为,可能不适用于所有新版Chrome/Firefox。 - 安全性: 原代码使用了被弃用的
mysql_connect且直接拼接变量生成SQL,极易遭受SQL注入攻击。必须迁移至PDO或MySQLi并使用预编译语句。 - 并发处理: 简单的轮询或单次触发在高并发下可能导致重复打印。建议引入锁机制或使用更完善的队列服务(如Redis Queue)。
- 移动端支持: 原思路主要针对桌面端IE环境,移动设备的打印机制差异较大,通常需要结合后端生成PDF或HTML文件供用户下载后再操作。
以上就是PHP简易云打印类实现的详细内容,更多关于PHP队列与Web打印的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









