摘要
本论文简要介绍了PHP、XML、PDF等技术的原理以及它们的应用情况。力图运用PHP面向对象的特性,构建出一套基于PHP和XML的在线PDF文档生成系统。文中详细探讨了整个系统的组成部分以及各自的实现过程。并在最后给出一个运用这套系统实现的动态创建报表的实例。
AbstractThis article introduced the fundamentls of PHP,XML and PDF and their application situation at present,expecting to build a PHP&XML-based dynamic PDF documents creating system through the PHP's OO features. Furthermore,we discussed in detail on the components of the whole system and their respective realizing methods. Finally,we represented an example of creating reports dynamically using this system.
关键词
PHP XML XSLT DTD PDF
1. 引言
在信息技术飞速发展的时代,无论政府、企业还是个人,他们对如何通过信息技术提高自身工作效率,节省开支具有浓厚的兴趣。他们急切要找到一种优秀的技术,可以把传统上以纸张为媒介的文件、报表、票单据、手册、申请书等等等等转化为一种可以非常方便的在互联网以及内部网络自动生成、传播、下载、浏览、打印的电子文档。而如今最为热门的“无纸化办公”、“电子商务”等等都将以此为基础。
这种文档格式就Adobe公司的PDF(可移植文档格式),它已是全世界电子版文档分发的公开实用标准 。 任何浏览器只要安装Acrobat reader 5.0 的插件,便可以自由浏览、下载、打印PDF文档。PDF无疑具有其它电子文档格式不可比拟的优越性。
我们知道B/S系统作为当前以及将来最流行的一种软件架构,可以很好的实现各种基于浏览器的Web应用程序,而PHP作为一种优秀的Web编程语言,特别适合开发用于处理用户表单输入,查询数据库等针对浏览器用户的前端应用程序。由于PHP是开放源码的,这使得它的使用比其它同类的Web脚本语言更为广泛,它的功能也在不断的扩充和完善之中。现在最新的PHP版本已经可以很好的支持PDF,XML等。通过系统提供的API,我们能非常快捷的生成PDF文档,而最具魅力的是,我们可以通过PHP,查询数据库或XML数据文件并将结果插入所生成的PDF文档之中,形成各种具有绝佳的浏览和打印效果的报表、单据、手册等。
不难看出,结合PHP、XML、PDF三项技术,构造出一种可以在线动态生成PDF文档的系统是极具现实意义的,其主要表现在:
·文档可以在网络上生成,并通过网络分发。节省大量的人力物力。具有精确美观的打印效果,真正实现了无纸化办公。
·电子商务交易过程中的各种票据、 凭证都可以通过PHP脚本程序在线生成,并转为PDF格式发送给客户。
·企业MIS系统中各种面向打印的报表的生成,并可直接通过浏览器获得,无须安装任客户端,使用极为方便。
·以前文件流转是"先打印,后分发",每年花在印刷上的费用是政府、企业沉重的负担。而PDF文档"先散发,后打印",接件人可以在浏览后,再按需要打印。印刷的费用大大减少。而且,很有利于环保事业。
2. 课题简介
在某些软件项目的开发过程中,我们遇到一个很关键的问题就是大量面向打印的报表、单据的生成。我们知道,HTML适合浏览,但不适合格式规范的打印。因此必需找到一种可以由PHP动态生成,且具有良好的打印效果的文档格式。而这正是我研究这个课题的最直接的需求。 明白了这一点,我们就很自然的想到了PDF以及PHP的PDF支持库PDFLib。通过PDFLib提供的一套API,我们可以很容易在PHP脚本动态创建PDF文档。但是这只是一套非常基本的函数,只能进行一些简单的输出,如线条、文本、矩形框等,而且每输出一个对象之前,都要为其指定坐标。如果直接使用来这套函数来做一些实际的应用,比如复杂的报表的生成,其困难程度是难以想象的。我们不可能为创建这样一个报表,而事先算好各个元素的坐标,并把单元格用矩形框一个一个的画出来。
所以,我们第一步要做的就是利用PHP面向对象的编程方法将这套基本的API进行封装,以产生多个实用的具有独立功能的对象模块(如page对象、table对象、text对象等)。应该说,这一块是此项目最基本,也是最重要的部分。我参考并部分采用
了国外一些类似的开放源码的程序,在此基础上开发出了一套功能较为强大的类库。大大简化了PDF文档的生成,特别是其中的table对象,可以象HTML中的TABLE标记一样任意嵌套,轻松快捷的实现各种复杂的表格的绘制(这对动态生成报表是非常有用的)。
生成PDF的问题解决以后,我们面临了新的问题,举个例子来说,数据库查询页面如何将包含大量信息的结果集以及其它信息传给PDF生成页面? 最初我们想到的方法是通过文本文件传递,即在数据库查询页面将数据写到一个文本文件当中,并对其
中不同类别的数据定义一套区分的标记,PDF生成页面读取此文件,将内容插入到PDF中。 但是这样做,并不可靠。因为在这个文本文件中,我们采用特定的字符(或空格)来分离数据,如果恰好有用数据中也包含同样的字符或空格呢?可见,以这种方式传递数据是有隐患的。其实上面我们提到在文本文件中用不同的标记区分不同类别的数据。而这正是XML技术的思想。何不一步到为采用XML来作为数据传递的手段呢? 况且PHP对XML和XSLT具有很好的支持,通过expat解析器,我们可以任意提取XML文档中的数据,也可以通过PHP的XSLT引擎Sablotron对XML文档进行任意转换。
首先由“XML生成器”将数据(来自数据库或用户输入等)放到一个符合事先定义好的DTD的XML文档中,此文档对其中的数据内容进行描述,不包含任何格式信息。 然后由“XML转换器”将这个XML文档转换成包含显示样式信息的另一个XML文档。 最后由“PDF生成器”读取这个文档,根据其中的内容和显示样式生成相应的PDF文档。在这一个过程中,我要做的是再次运用 PHP的面向对象特性,构建出可重用的类:XMLWriter(生成XML文件)、XMLParser(解析XML文件)以及XMLTransformer(对XSLT函数的封装)。
系统构建成功后,就是具体的应用了。主要是进销存系统中各种报表、单据的动态生成。
3. 可行性分析
开发一个功能强大、适应性好的PDF文档在线生成系统,必然需要弹性大、灵活性
高的开发模型。我们提出的基于PHP和XML的PDF文档在线生成技术,为各种面向打印的应用,如报表、单票据、手册等提供了新的思路。我们用PHP来查询数据库,处理用户输入,并在此基础上生成原始的XML文档;然后通过XSLT将该XML文档加上显示层信息,生成另外一个新的XML文档。最后利用“PDF生成器”将这个新的XML文档转化为相应格式的PDF文档。对于最初生成的XML文档,我可以做二度利用,因为该文档包含了所有的有用信息,可以非常容易的被其它应用程序处理。如果我们想改变信息在PDF文档显示的样式,可以非常容易的实现。只要专门人员修改相应的XSL样式单文件即可,不需要对其它环节做任何修改,具有非常好的灵活性。除此之外,PHP、XML、PDF三者都具有极好的可移植性,可以跨平台使用。 对该系统的研究并非凭空想象的,它建立在直接的需求之上的。到目前为止,这套技术已经投入实际应用,收到了极为满意的效果。实践证明,运用PHP和XML开发出的一套在线PDF文档生成系统具有广阔和非常实际的应用前景。
4 总体设计
本课题主要完成四个基础模块的设计及编程实现。这四个类模块分别为PDFCreator、XMLWriter、XMLTransfomer以及XMLParser。它们分布于系统的各个环节之中,具有各自独立的功能和作用,是系统的核心组成部分(见下图)。
系统构成图
从图中可见,四者在本系统中又是紧密联系的有机整体。XMLWriter作为系统的输
入接口,负责生成原始的XML数据文件。该文件的格式规范(DTD)由我们事先编写好,而XMLWriter按照该DTD生成相应的XML文档。这个XML文档接着交由XMLTransfomer处理,XMLTransfomer其实是对PHP提供的XSLT函数的封装,它一般接受两个参数,其中之一是需要转换的XML文档,另一个是相应的XSL样式单文件。XMLTransfomer正是根据该样式单文件将原始的XML文档转化为符合这个样式单样式的另一个XML文档(包含信息在PDF文档中放置的格式)。然后,这个新的XML文件继续交由“PDF生成器”进行处理。而这个过程有分为两个部分:首先,必需对这个XML文档进行解析,提取其中所需的数据,这一步有XMLParser来完成,XMLParser对此XML文档进行解析,将其转化为一棵对象树,XML文档中每一个节点都是一个对象,每个对象都有各自的属性(即相应节点的所有信息)。这样一来,我们可以非常方便的访问这个XML文档的任意内容。之后,要做的就是将该XML文档中读出的信息(包括格式信息和内容信息)用PDFCreator转化为最终的PDF文档的输出。
5.应用示例
在这里,我们运用上面的这套系统创建一个面向打印的报表——“库存历史事
表”。这个报表包含的信息有:报表名称(协和库存历史事务表)、单位、建表日期等,另外就是从数据库中提取的数据了,品名(LLPROD)、批号(LLOC)、等级(LCLS)、仓库(LWHS)、库位(LLOCT)、数量(LNUM)、日期(LDATE)等。假设我们已经用XMLWriter生成了下面的原始XML文档(report.xml):
<?xml version="1.0" encoding="gb2312"?>
<report>
<report_param>
<title>库存历史事务表</title>
<unit>平方米</unit>
<date>20020611</date>
</report_param>
<report_records>
<record>
<llprod>W2308</llprod>
<lloc>1234</lloc>
<lcls>a</lcls>
<lwhs>01</lwhs>
<lloct>0001</lloct>
<lnum>200</lnum>
<ldate>20020609</ldate>
</record>
<record>
<llprod>W2307</llprod>
<lloc>4321</lloc>
<lcls>a</lcls>
<lwhs>01</lwhs>
<lloct>0001</lloct>
<lnum>100</lnum>
<ldate>20020609</ldate>
</record>
</report_records>
</report>
该文档包含了这张报表的所有有用信息,我们需要用特定的XSL样式单为其加上格式信息。XMLTransformer执行转换的代码如下:
<?php
$xslt = new XMLTransformer ("report.xsl", "report.xml");
$xslt->apply("pdfreport.xml");
?>
转换后生成的新的XML文档如下:
<?xml version="1.0" encoding="gb2312"?>
<pdfreport pagetype="a4" pagesize="25" top="20" bottom="20" left="20" right="20">
<head>
<line top="5" bottom="5" size="50%" linetype="single" show="false"/>
<text fontsize="30" fontlaguage="cn" align="center">库存历史事务表</text>
<line top="5" bottom="30" size="80%" linetype="double" show="true"/>
<text fontsize="12" fontlaguage="cn" align="left">单位:平方米</text>
</head>
<body>
<table>
<tr><th>品名</th><th>批号</th><th>等级</th><th>仓库</th><th>库位</th><th>数量</th><th>日期</th></tr>
<tr><td>W2308</td><td>1234</td><td>a</td><td>01</td><td>0001</td><td>200</td><td>20020609</td></tr>
<tr><td>W2307</td><td>4321</td><td>a</td><td>01</td><td>0001</td><td>100</td><td>20020609</td></tr>
</table>
</body>
<foot>
<line top="5" bottom="5" size="50%" linetype="single" show="false"/>
<text fontsize="12" fontlaguage="cn" align="center">建表日期:20020611</text>
</foot>
</pdfreport>
用XMLParser对该XML文档解析后,得到一个包含所有信息的对象树,我们可以非常方便的访问其中的内容。生成的PDF报表如下图:
程序片断如下:
<? include( "../include/pc_init.inc" );?>
<? include( "xmlparser.inc" );
<?
$xmlobject=getRootNode("report.xml");
// get the attrs of root element
$pageSet=$xmlobject->attrs;
// get the report-head
$head=$xmlobject->nodes[0];
// code ignored...
?>
<?
function draw_line(&$parent,$line){
$line = &pc_create_object( $parent, "line" );
$line->pc_set_linestyle( $line->attrs["LINETYPE"]);
$line->pc_set_width( $line->attrs["SIZE"] );
$line->pc_set_alignment( "center" );
if($line->attrs["SHOW"]==false){
$line->pc_set_linecolor( "white" );
}
$line->pc_set_margin( array( "top" => $line->attrs["TOP"], "bottom" => $line->attrs["BOTTOM"], "left" => 0, "right" => 0 ) );
}
function draw_text(&$parent,$text){
// code ignored...
}
function draw_table(&$parent,$table){
// code ignored...
}
function addhead(&$parent,$head){
for($i=0;$i< $head->n;$i++){
switch ($head->nodes[$i]->name){
case "LINE":draw_line($parent,$head->nodes[$i]);break;
case "TEXT":draw_text($parent,$head->nodes[$i]);break;
}
}
}
//..
?>
<?
// Create a PDF Document
$PDF = &pc_create_pdf( array( "Author" => "cyman", "Title" => "a report example" ) );
// Create an A4-format page
$Page1 = &pc_create_page( $PDF, $pageSet["PAGETYPE"]);
addhead($Page1,$head);
$PDF->pc_draw();
?>
6.总结
在几个月来的毕业设计过程中,虽然忙碌,却非常充实。通过对一个实际的课题的分析,研究,论证,实现。感觉收获颇多。目前,这套系统已投入使用,收到了非常满意的效果,可以很容易的做出美观实用的报表、单据等。但是,由于时间上的仓促以及自己水平的有限,这套系统仍有许多不足之处。其中最遗憾就是,没有能定义出一套对各种文档(包括报表、单据、手册等等)都通用的XML标记,并编制通用的程序将这个XML文档转化为PDF,就如同浏览器解析HTML一样。这样就不必为每一种文档都定义各自的XML标记并编写相对应的转换程序,可以大大提高工作效率。
虽然毕业设计已经结束,但是我将会今后的日子里继续这个课题的研究。
該方法已經屬於過時方法,其中關鍵的地方也從論壇上得來的,我只是把它消化吸收后重新写了更全面的出来。公布出來只是希望更多的新手能從中學到一些東西。如果你對該代碼有任何意見可以留言,但請勿進行人身攻擊,我是一個菜鳥只能寫出這樣的東西,每个老鸟都有这样的过程。
鉴于时间问题,代碼的提交部分使用的是传统的表单POST,如果您喜欢可以根据LOAD过程自行加上相应的SCRIPT,不过好像只
能用GET了。聽說XML可以實現真正的無刷新,如果誰手上有希望能借來看看。
在此感謝QQ群組中蓝劍雪狐和shelly水在JS上給予的幫助,也新手們能把自己寫的功能代碼貼出來大家一起來學習研究。
最後附上演示地址:http://lfox0002.dns0755.net/text_input.php 請喜歡HACK他人機器的朋友們手下留情,附上演示是為了讓朋友們能更快了解代碼。
input.php[HTML] 接受用户输入数据。
PHP代码:----------------------------------------------
<?php
/*
申 明
------------------------------
该演示文件详细描述了利用JS+PHP对数据库进行類似無刷新读出写入的方法
2004年02月14日
By L.Fox
*/
header("Cache-Control: no-store, no-cache,must-revalidate"); //這兩行可以取消,把文件存成HTML
echo $_POST["name1"]; //我是為了?#123;試方便才加的。
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=??????">
<title>根据编号从MYSQL提取数据进行编辑并回存[演示]</title>
<script language="JavaScript" id="LoadDataSrc"></script>
<style>
body {
font-family: "Verdana", "Arial", "Helvetica", "sans-serif";
font-size: 12px;
line-height: 17px;
scrollbar-base-color: #BBBBBB;
scrollbar-shadow-color: #BBBBBB;
scrollbar-highlight-color: #FFFFFF;
scrollbar-3dlight-color: #000000;
scrollbar-darkshadow-color: #000000;
scrollbar-arrow-color: #FFFFFF;
}
table {
border: 0;
font-size: 12px;
cursor: default;
}
td {
text-align: left;
height: 20;
}
input {
width: 100;
height: 18;
border: 0px solid #666666;
text-align: left;
}
</style>
<script>
var objInput = null;
var objTd = null;
var num =null;
function AutoEdit(obj,id)
{
if (objInput == null)
{
objTd = obj;
obj.innerHTML = "<input size=\"10\" maxlength=\"10\" type=\"text\" value=\"" + obj.innerText + "\"
id=\"objInput\" onblur=\"objTd.innerText=this.value;LoadData(objTd.innerText,num);objInput=null;\" overflow:
visible;border:none;background-color:#EFEFEF\">";
objInput = document.getElementById("objInput");
objInput.focus();
}
}
function LoadData(LoadIndex,LoadObj)
{
var LoadFileName="load.php?action="/blog_article/LoadIndex/index.html"&num=" + LoadObj;
document.getElementById("LoadDataSrc").src = LoadFileName;
}
function OutPutData(obj)
{
if (form1.num1.value.length<1){ alert("请输入数量1"); return false;}
if (form1.num2.value.length<1){ alert("请输入数量2"); return false;}
if (document.getElementById("name1").innerHTML.length<1){ alert("name1空值"); return false;}
if (document.getElementById("name2").innerHTML.length<1){ alert("name2空值"); return false;}
obj.innerHTML="<input type=\"hidden\" name=\"name1\" value=\"" + document.getElementById("name1").innerHTML + "\">";
obj.innerHTML+="<input type=\"hidden\" name=\"name2\" value=\"" + document.getElementById("name2").innerHTML + "\">";
obj.innerHTML+="<input type=\"hidden\" name=\"type1\" value=\"" + document.getElementById("type1").innerHTML + "\">";
obj.innerHTML+="<input type=\"hidden\" name=\"type2\" value=\"" + document.getElementById("type2").innerHTML + "\">";
obj.innerHTML+="<input type=\"hidden\" name=\"date1\" value=\"" + document.getElementById("date1").innerHTML + "\">";
obj.innerHTML+="<input type=\"hidden\" name=\"date2\" value=\"" + document.getElementById("date2").innerHTML + "\">";
obj.innerHTML+=form1.submit();
}
function postdata()
{
form1.submit();
}
</script>
</head>
<body>
<form name="form1" method="post" action="/blog_article/load/action/OutPutData.html">
<table width="400" cellpadding="0" cellspacing="1" align="center" bgcolor="#999999">
<tr bgcolor="#EFEFEF">
<td onclick="AutoEdit(this,num=1)" ><div></div></td>
<td onclick="AutoEdit(this,num=2)" ><div></div></td>
</tr>
<tr bgcolor="#EFEFEF">
<td><div id="name1" >a</div></td>
<td><div id="name2" >b</div></td>
</tr>
<tr bgcolor="#EFEFEF">
<td><div id="type1" >a</div></td>
<td><div id="type2" >b</div></td>
</tr>
<tr bgcolor="#EFEFEF">
<td><div id="date1" ></div></td>
<td><div id="date2" ></div></td>
</tr>
<tr bgcolor="#EFEFEF">
<td><div><input type="text" name="num1" value=""></div></td>
<td><div><input type="text" name="num2" value=""></div></td>
</tr>
<div id="OutPutData"><a href="#" onclick="java script:OutPutData(this);">输出</a></div></form>
</body>
</html>
------------------------------------------------------
LOAD.php
PHP代码:-----------------------------------------------
<?php
header("Cache-Control: no-store, no-cache,must-revalidate");
include("obj/financial_obj_free.inc"); //这个文件里的内容是连接MYSQL的语句。
$str=$_GET["action"];
$num=$_GET["num"];
if ($str=="OutPutData") OutPutData();
else
{
linkdata("financial",1);
$sql="select * from table where id='$str'";
if ($query=mysql_query($sql))
{
$temdata=mysql_fetch_row($query); //看看是不是空的,如果是就附上值以免JS报错。
if (strlen($temdata[2])<1||$temdata[2]=="") $temdata[2]="空";
$temdata[2]=htmlspecialchars($temdata[2]);
if (strlen($temdata[3])<1||$temdata[3]=="") $temdata[3]="空";
$temdata[3]=htmlspecialchars($temdata[3]);
if (strlen($temdata[5])<1||$temdata[5]=="") $temdata[5]="空";
$temdata[5]=htmlspecialchars($temdata[5]);
}
else
{
$temdata[2]=$temdata[3]=$temdata[5]="查询失败";
}
switch ($num) //这个主要是用于检查是从第几列(行)传过来的。注意变量值要与input的id值对应好.否则出错
{
case 1:
$diva="name1";
$divb="type1";
$divc="date1";
break;
case 2:
$diva="name2";
$divb="type2";
$divc="date2";
break;
default:
$diva="name1";
$divb="type1";
$divc="date1";
break;
}
//确定节点,输出$temdata[X]到节点$divX;
echo "document.getElementById('".$diva."').innerHTML='".$temdata[2]."';";
echo "document.getElementById('".$divb."').innerHTML='".$temdata[3]."';";
echo "document.getElementById('".$divc."').innerHTML='".$temdata[5]."';";
}
function OutPutData() //这下面如果改成SQL语句就可以写进数据库
{
echo "输出的数据如下,改成SQL语句然后就可以保存下来";
echo "编号1=".$_POST["name1"]."<br>";
echo "编号2=".$_POST["name2"]."<br>";
echo "名称1=".$_POST["type1"]."<br>";
echo "名称2=".$_POST["type2"]."<br>";
echo "日期1=".$_POST["date1"]."<br>";
echo "日期2=".$_POST["date2"]."<br>";
echo "数量1=".$_POST["num1"]."<br>";
echo "数量2=".$_POST["num2"]."<br>";
echo "<a href=/index.html"text_input.php\">返回</a>";
}
?>
【1】页面之间无法传递变量 get,post,session在最新的php版本中自动全局变量是关闭的,所以要从上一页面取得提交过来得变量要使用$_GET['foo'],$_POST['foo'],$_SESSION['foo']来得到
当然也可以修改自动全局变量为开(php.ini改为register_globals = On);考虑到兼容性,还是强迫自己熟悉新的写法比较好。
【2】Win32下apache2 用get方法传递中文参数会出错
test.php?a=你好&b=你也好
传递参数是会导致一个内部错误
解决办法:"test.php?a=".urlencode(你好)."&b=".urlencode(你也好)
.............
【3】win32下的session不能正常工作
php.ini默认的session.save_path = /tmp
这显然是linux下的配置,win32下php无法读写session文件导致session无法使用
把它改成一个绝对路径就可以了,例如session.save_path = c:\windows\temp
【4】显示错误信息
当php.ini的display_errors = On并且error_reporting = E_ALL时,将显示所有的错误和提示,调试的时候最好打开以便纠错,如果你用以前php写法错误信息多半是关于未定义变量的。变量在赋值以前调用会有提示,解决办法是探测或者屏蔽
例如显示$foo,可以if(isset($foo)) echo $foo 或者echo @$foo
【5】Win32下mail()不能发送电子邮件
在linux下配置好的sendmail可以发送,在win32下需要调用smtp服务器来发送电子邮件
修改php.ini的SMTP = ip //ip是不带验证功能的smtp服务器(网上很难找到)
php发送邮件的最好解决方法是用socket直接发送到对方email服务器而不用转发服务器
【6】初装的mysql如果没有设置密码,应该使用
update mysql.user set password="yourpassword" where user="root"
修改密码
【7】header already sent
这个错误通常会在你使用HEADER的时候出现,他可能是几种原因:1,你在使用HEADER前PRING或者ECHO了2.你当前文件前面有空行3.你可能INCLUDE了一个文件,该文件尾部有空行或者输出也会出现这种错误。!
【8】更改php.ini后没有变化
重新启动web server,比如IIS,Apache等等,然后才会应用最新的设置
【9】php在2003上面安装(ISAPI的安装方法恳请高手指教)
PHP4的php4isapi.dll好像和2003有些冲突,只能用CGI模式安装
步骤一,先www.php.net下在一个安装程序,我是装的是:php-4.2.3-installer.exe,你也可以去找最新的版本,在安装php-4.2.3-installer.exe之前保证你的IIS6.0启动了,并能够访问。 安装好以后,在默认网站-->应用程序配置
步骤二:点击 web服务扩展 -->新建web服务扩展.
步骤三: 扩展名-->php,然后添加
步骤四:找到php.exe的路径添加上去。
步骤五: 确定就可以了!
步骤六: 选择php的服务扩展,然后点击允许。
【10】
有时候sql语句不起作用,对数据库操作失败
最简便的调试方法,echo那句sql,看看变量的值能得到不
【11】include和require的区别
两者没有太大的区别,如果要包含的文件不存在,include提示notice,然后继续执行下面的语句,require提示致命错误并且退出
据我测试,win32平台下它们都是先包含后执行,所以被包含文件里最好不要再有include或require语句,这样会造成目录混乱。或许*nux下情况不同,暂时还没测试
如果一个文件不想被包含多次可以使用include_once或require_once## 读取,写入文档数据
function r($file_name) {
$filenum=@fopen($file_name,"r");
@flock($filenum,LOCK_SH);
$file_data=@fread($filenum,filesize($file_name));
@fclose($filenum);
return $file_data;
}
function w($file_name,$data,$method="w"){
$filenum=@fopen($file_name,$method);
flock($filenum,LOCK_EX);
$file_data=fwrite($filenum,$data);
fclose($filenum);
return $file_data;
}
【12】isset()和empty()的区别
两者都是测试变量用的
但是isset()是测试变量是否被赋值,而empty()是测试一个已经被赋值的变量是否为空
如果一个变量没被赋值就引用在php里是被允许的,但会有notice提示
如果一个变量被赋空值,$foo=""或者$foo=0或者 $foo=false,那么empty($foo)返回真,isset($foo)也返回真,就是说赋空值不会注销一个变量。
要注销一个变量,可以用 unset($foo)或者$foo=NULL
【13】mysql查询语句包含有关键字
php查询mysql的时候,有时候mysql表名或者列名会有关键字
这时候查询会有错误。例如表名是order,查询时候会出错
简单的办法是sql语句里表名或者列名加上`[tab键上面]来加以区别
例如select * from `order`
【14】通过HTTP协议一次上传多个文件的方法
有两个思路,是同一个方法的两种实现。具体程序还需自己去设计
1,在form中设置多个文件输入框,用数组命名他们的名字,如下:
<form action="" method=post>
<input type=file name=usefile[]>
<input type=file name=usefile[]>
<input type=file name=usefile[]>
</form>
这样,在服务器端做以下测试
echo "<pre>";
print_r($_FILES);
echo "</pre>";
1,在form中设置多个文件输入框,但名字不同,如下:
<form action="" method=post>
<input type=file name=usefile_a>
<input type=file name=usefile_b>
<input type=file name=usefile_c>
</form>
在服务器端做同样测试:
echo "<pre>";
print_r($_FILES);
echo "</pre>";