从零开始PHP攻略(3)——数据的存储与检索
要点目录:
1.保存数据的方法
存储数据有两种基本方法:保存到普通文件,或者保存到数据库中。当具有大量订单时,应该使用一个数据库管理系统。
2.订单添加收货地址
本篇将使用上一篇所介绍的订单的改进版本。
Html代码如下:
<html>
<head>
<title>Bob's Auto Parts</title>
</head>
<body>
<h1>Bob's Auto Parts</h1>
<h2>Order Form</h2> <form action="processorder.php" method="post">
<table border="0">
<tr bgcolor="#cccccc">
<td width="150">Item</td>
<td width="15">Quantity</td>
</tr>
<tr>
<td>Tires</td>
<td align="left"><input type="text" name="tireqty" size="3" maxlength="3"/></td>
</tr>
<tr>
<td>Oil</td>
<td align="left"><input type="text" name="oilqty" size="3" maxlength="3"/></td>
</tr>
<tr>
<td>Spark Plugs</td>
<td align="left"><input type="text" name="sparkqty" size="3" maxlength="3"/></td>
</tr>
<tr>
<td>Shipping Address</td>
<td align="center"><input type="text" name="address" size="40" maxlength="40"/></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="Submit Order"/></td>
</tr>
</table>
</form> </body>
</html>
3.打开文件
fopen()函数可以打开一个文件。
$fp = fopen(“$DOCUMENT_ROOT/orders.txt”,’w’);
由于我们为表单变量定义了一个简短名称,我们需要在脚本的开始处加上如下代码:
$DOCUMENT_ROOT = $_SERVER[‘DOCUMENT_ROOT’];
可以通过如下3种方式得到文档根目录:
$_SERVER[‘DOCUMENT_ROOT’] $DOCUMENT_ROOT $HTTP_SERVER_VARS[‘DOCUMENT_ROOT’]
fopen()有四个参数,其中第一个参数是路径。
第二个参数是文件模式。
第三个参数可选,如果要在include_path中搜索一个文件,就可以使用它。
第四个参数也可选,fopen()函数允许文件名称以协议名称开始并且在一个远程的位置打开文件。
也可以使用fopen()函数通过FTP、HTTP或其他协议来打开文件。
注意,URL中的域名不区分大小写,但是路径和文件名可能会区分大小写。
4.打开文件时可能遇到的问题
设置了不正确的访问权限可能是造成打开文件时出现错误的常见原因。
任何人都可以写的目录和文件时非常危险的,后面的文章会详细介绍安全问题。
If语句可以用来测试变量$fp,查看fopen()函数是否返回了一个有效的文件指针。
@$fp = fopen("$DOCUMENT_ROOT/orders.txt", 'ab'); if (!$fp) { echo "<p><strong> Your order could not be processed at this time. Please try again later.</strong></p></body></html>"; exit; }
用自己的错误信息替代PHP的错误信息可以使用户觉得更加友好。
5.写文件
可以使用fwrite()写文件。
int fwrite(resource handle, string string [, int length])
第一个参数是文件。第二个参数是数据。第三个参数可选,是最大字符数。可以通过PHP的内置strlen()函数获得字符串的长度:
fwrite($fp, $outputstring, strlen($outputstring));
定义保存的数据格式:
$outputstring = $date."\t".$tireqty." tires \t".$oilqty." oil\t" .$sparkqty." spark plugs\t\$".$totalamount ."\t". $address."\n";
选择每行记录一个订单这种格式是因为这样可以使用换行字符作为简单的记录间隔符。
处理了一些订单后,该文件的内容将类似如下:
08:00, 9th August 2016 1 tires 1 oil 1 spark plugs $114.00 s
08:51, 9th August 2016 1 tires 1 oil 1 spark plugs $114.00 s
08:51, 9th August 2016 112 tires 121 oil 111 spark plugs $12 854.00 sasdf
6.关闭文件
按照如下方式调用fclose()函数即可:
fclose($fp)
订单处理脚本processorder.php源码:
<?php
// create short variable names
$tireqty = $_POST['tireqty'];
$oilqty = $_POST['oilqty'];
$sparkqty = $_POST['sparkqty'];
$address = $_POST['address'];
$DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
$date = date('H:i, jS F Y');
?>
<html>
<head>
<title>Bob's Auto Parts - Order Results</title>
</head>
<body>
<h1>Bob's Auto Parts</h1>
<h2>Order Results</h2>
<?php echo "<p>Order processed at ".date('H:i, jS F Y')."</p>"; echo "<p>Your order is as follows: </p>"; $totalqty = 0;
$totalqty = $tireqty + $oilqty + $sparkqty;
echo "Items ordered: ".$totalqty."<br />"; if ($totalqty == 0) { echo "You did not order anything on the previous page!<br />"; } else { if ($tireqty > 0) {
echo $tireqty." tires<br />";
} if ($oilqty > 0) {
echo $oilqty." bottles of oil<br />";
} if ($sparkqty > 0) {
echo $sparkqty." spark plugs<br />";
}
} $totalamount = 0.00; define('TIREPRICE', 100);
define('OILPRICE', 10);
define('SPARKPRICE', 4); $totalamount = $tireqty * TIREPRICE
+ $oilqty * OILPRICE
+ $sparkqty * SPARKPRICE; $totalamount=number_format($totalamount, 2, '.', ' ');//通过千位分组来格式化数字 echo "<p>Total of order is $".$totalamount."</p>";
echo "<p>Address to ship to is ".$address."</p>"; $outputstring = $date."\t".$tireqty." tires \t".$oilqty." oil\t"
.$sparkqty." spark plugs\t\$".$totalamount
."\t". $address."\n"; // open file for appending
@ $fp = fopen("$DOCUMENT_ROOT/orders.txt", 'ab'); flock($fp, LOCK_EX); //写操作锁定 if (!$fp) {
echo "<p><strong> Your order could not be processed at this time.
Please try again later.</strong></p></body></html>";
exit;
} fwrite($fp, $outputstring, strlen($outputstring));
flock($fp, LOCK_UN); //释放锁定
fclose($fp); echo "<p>Order written.</p>";
?>
</body>
</html>
7.读文件
用来查看订单文件的员工界面:
<?php
//create short variable name
$DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
?>
<html>
<head>
<title>Bob's Auto Parts - Customer Orders</title>
</head>
<body>
<h1>Bob's Auto Parts</h1>
<h2>Customer Orders</h2>
<?php @$fp = fopen("$DOCUMENT_ROOT/orders.txt", 'rb'); //只读模式 flock($fp, LOCK_SH); // lock file for reading if (!$fp) {
echo "<p><strong>No orders pending.
Please try again later.</strong></p>";
exit;
} while (!feof($fp)) {
$order= fgets($fp, 999);
echo $order."<br />";
} echo "Final position of the file pointer is ".(ftell($fp)); //指针当前位置
echo "<br />";
rewind($fp);
echo "After rewind, the position is ".(ftell($fp)); //指针复位
echo "<br />"; flock($fp, LOCK_UN); // release read lock fclose($fp); ?>
</body>
</html>
这段脚本是按照前面所介绍的步骤进行的:打开文件、读文件、关闭文件。下面进行详细说明。
7.1 知道何时读完文件:feof()
使用feof()函数作为文件结束的测试条件:
while(!feof($fp))
函数feof()的唯一参数是文件指针。如果该文件指针指向了文件末尾,它将返回true。feof表示File End Of File。
7.2 每次读取一行数据:fgets()、fgetss()和fgetcsv()
这个例子中使用了fgets()函数来读取文件内容:
$order = fgets($fp, 999);
这个函数可以从文件中每次读取一行内容。这样,它将不断地读入数据,直至读到一个换行字符(\n)、或者文件结束符EOF,或者是从文件中读取了998B。可以读取的最大长度为指定的长度减去1B。
出于操作安全的考虑可以使用fgetss()函数:
string fgetss(resource fp, int length, string [allowable_tags]);
如果希望重新构建订单中的变量,而不是将整个订单作为一行文本,使用fgetcsv()函数可以很容易实现。
array fgetcsv( resource fp, int length [, string delimiter[, string enclosure]])
7.3 读取整个文件:readfile()、fpassthru()和file()
有四种方式可以一次读取整个文件:
1)readfile()
readfile(“$DOCUMENT_ROOT/orders.txt”);
调用readfile()函数将打开这个文件,并且将文件内容输出到标准输出中,然后再关闭这个文件。readfile()的函数原型如下:
int readfile(string filename, [int use_include_path [, resource context]]);
第二个可选参数指定了PHP是否应该在include_path中查找文件。
2)fpassthru()
要使用这个函数,必须先使用fopen()打开文件。然后将文件指针作为参数传递给fpassthru()。
可以使用如下代码替代前面的脚本:
$fp = fopen(“$DOCUMENT_ROOT/orders.txt”,’rb’); fpassthru($fp);
3)file()
除了可以将文件内容会显到标准输出外,它和readfile()是一样的。
4)file_get_contents()
与readfile()基本相同。不同之处是该函数将以字符串的形式返回文件内容,而不是将文件内容回显到浏览器中。
7.4 读取一个字符:fgetc()
while(!feof($fp)){ $char = fgetc($fp); if(!feof($fp)){ echo ($char == “\n”?”<br />”:$char); } }
这段代码使用fgetc()函数从文件中一次读取一个字符,并且将该字符保存在$char中,直到文件结束。然后再用HTML的换行符(<br />)替换文本中的行结束符(\n)。
使用fgetc()函数的一个缺点就是它返回文件结束符EOF,而fgets()则不会。读取出字符后还需要判断feof(),因为我们并不希望将文件结束符EOF回显到浏览器中。
7.5 读取任意长度:fread()
String fread(resource fp, int length);
8.使用其他有用的文件函数
8.1 查看文件是否存在:file_exists()
if(file_exists(“$DOCUMENT_ROOT/orders.txt”)){ echo ‘There are orders waiting to be processed.’; }
else{ echo ‘There are currently no orders.’; }
8.2 确定文件大小:filesize()
echo filesize(“$DOCUMENT_ROOT/orders.txt”);
8.3 删除一个文件:unlink()
unlink(“$DOCUMENT_ROOT/orders.txt”);
通常,如果对该文件的访问权限不够或者该文件不存在,该函数将返回false。
8.4 在文件中定位:rewind()、fseek()和ftell()
rewind()函数可以将文件指针复位到文件的开始。
ftell()函数可以以字节为单位报告文件指针当前在文件中的位置。
fseek()函数将文件指针指向文件的某个位置:
int fseek( resource fp, int offset[, int whence])
9.文件锁定
假设两个客户试图同时订购同一件商品,可以使用文件锁定的方法。当一个文件被打开并且在进行读写操作之前,应该调用这个函数。
bool flock(resource fp, int operation [, int & wouldblock])
还必须将一个指向被打开文件的指针和一个表示所需锁定类型的常数作为参数传递给这个函数。如果文件锁定成功,其返回值为true,否则为false。如果获得文件锁将导致当前的进程被阻塞,可选的第三个参数将包含值true。
operation参数的可能值:
LOCK_SH:读操作锁定
LOCK_EX:写操作锁定
LOCK_UN:释放已有的锁定
LOCK_NB:防止在请求加锁时发生阻塞
flock()函数无法在NFS或其他网络文件系统中使用。在某些操作系统中,它是在进程级别上实现的,如果你在多线程服务器API中使用,该函数也无法正确使用。
如果有两个脚本同时申请对一个文件加锁,就需要使用数据库管理系统(DBMS)。
10.更好的方式:数据库管理系统
相比使用普通文件的优势:
1)更快的数据访问
2)易查找并检索满足特定条件的数据集合
3)具有内置的处理并发访问的机制
4)可以随机访问数据
5)具有内置的权限系统
后面的文章会详细介绍数据库。
整理自《PHP与MySQL Web开发》
从零开始PHP攻略(3)——数据的存储与检索的更多相关文章
- 从零开始PHP攻略(001)——Bob的汽车零部件商店
1.创建订单表单 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...
- 从零开始PHP攻略(2)——操作符与迭代整理
目录: 10.操作符整理 11.表单计算代码 12.优先级与结合性 13.可变函数 14.条件判断 15.循环迭代 16.跳出控制 17.可替换的控制结构 10.操作符 10.1 算术操作符 算术操作 ...
- 从零开始PHP攻略(000)——关于WAMPServer集成环境
Apache.PHP和MySQL都可以用于多种操作系统和Web服务器的组合.本篇介绍在Windows下用WampServer环境包来搭建本地php环境. W:windows A:Apache M:My ...
- PHP学习(3)——数据的存储与检索
要点目录: I.保存数据 II.打开文件 III.创建并写入文件 IV.关闭文件 V.读文件 VI.给文件加锁 VII.删除文件 VIII.其他有用的文件操作函数 IX.数据库管理系统 1.保存数 ...
- PHP对文件数据的存储和检索
@(主要是对文件的操作) 文件处理:php操作文件主要是写入和读取这两种.执行的步骤都是一样的. 1.打开这个文件.如果打不开就先创建它.2.将数据写入这个文件,或者将数据读出这个文件.3.关闭文件. ...
- 从零开始攻略PHP(9)——错误和异常处理
1.Exception类 这个类是PHP为异常处理提供的内置类.构造函数的两个参数分别是错误消息和错误代码. 除了构造函数之外,该类还提供了如下的内置方法: · getCode() 返回传递给构造函数 ...
- 全栈数据工程师养成攻略:Python 基本语法
全栈数据工程师养成攻略:Python 基本语法 Python简单易学,但又博大精深.许多人号称精通Python,却不会写Pythonic的代码,对很多常用包的使用也并不熟悉.学海无涯,我们先来了解一些 ...
- JAVA EE企业级开发四步走完全攻略 [转]
http://bbs.51cto.com/thread-550558-1.html 本文是J2EE企业级开发四步走完全攻略索引,因内容比较广泛,涉及整个JAVA EE开发相关知识,这是一个长期的计划, ...
- 【JAVA EE企业级开发四步走完全攻略】
本文是J2EE企业级开发四步走完全攻略索引,因内容比较广泛,涉及整个JAVA EE开发相关知识,这是一个长期的计划,单个发blog比较零散,所以整理此索引,决定以后每发一季JAVA EE blog后会 ...
随机推荐
- Yii源码阅读笔记(十五)
Model类,集中整个应用的数据和业务逻辑——验证 /** * Returns the attribute labels. * 返回属性的标签 * * Attribute labels are mai ...
- 导入maven项目后无法找到sun tools toos-15.0.jar
直接在缺失该jar包的pom中添加 以下属性和依赖即可! <java.home>D:\devtool\jdk1.6</java.home> <!-- 指定使用的JDK的安 ...
- CSS布局总结
三种布局模型: 1.flow 标准流布局 2.float 浮动布局 3.layer 层叠布局 关于(flow) 标准流布局 浏览器默认的布局方式就是标准流布局.对于标准流布局下的的块元素和行内元素的特 ...
- Aliasing 走样
Computer Science An Overview _J. Glenn Brookshear _11th Edition Have you ever noticed the weird &quo ...
- 弹窗文件js+css
// 每个弹窗的标识 var x =0; var idzt = new Array(); var Window = function(config){ //ID不重复 idzt[x] = " ...
- Android 环境快速搭建-详细步骤-win7-64bit
电脑装了win7 64位的系统,重新来搭建了安卓环境,发现有一种非常便捷,快速的方法就可以搭建起来了~ 步骤一:下载java sdk 进入http://www.oracle.com/us/sun/in ...
- backgroundworker的应用
一种情况是当凭证界面加载时,因为加载项比较多,辅助项的处理,可以应用backgroundworker启用另一线程进行加载,不影响当前界面的显示,提高响应速度. 情况2 是月末结转余额时,因为用时间较长 ...
- 用Intellij IDEA 创建第一个maven项目!
1. 一直想如何复用以前项目的maven的jar包! 其实只要拿到pom.xml即可!!! 1.1 创建一个maven项目 2. 3. 创建项目名和项目路径,我给项目起的名字是mavenV1.0 4. ...
- 3. 如何封装查询条件与查询结果到map中
public Map<String, Object> queryOrderStatus(String orderNo) { // 查询到的结果与查询的条件一一对应,封装到map中! Str ...
- asm/aam links
http://personalpages.manchester.ac.uk/staff/timothy.f.cootes/asm_links.html