PHP功能的强大首先在于它的大量的内置函数库,它可以让初学者也能执行许多复杂的任务,而不必安装新的库和关心底层的详细情况,而这恰恰是其它流行的诸如Perl这样的客户端语言所不具备的。由于这个教程的限制,我们仅仅学习了一些与MySQL数据库相关的一些函数(事实上,即使是这种函数,我们也没有学全)。在这最后的部分,我们会稍微扩大一下范围来看看其它对于建立一个数据库驱动的网站有用的PHP的特征。

我们首先将学习PHP的include函数,使用这个函数,我们可以在许多页面中重复使用同一个PHP代码段。我们还看到如何利用这个函数提高我们的网站的安全性。

虽然PHP一般是相当快速和有效率的,但是它会加重服务器的运行时间和工作量。对于一个高流量的站点来说,这种负担可能会达到无法接受的程度。但是这并不意味着我们需要放弃我们的站点的数据库驱动的特征。我们会看到如何使用PHP在后台建立半动态页面而不必过分加重服务器的负担。

经常有人问论坛是如何利用一个标记来接受文件的上载的。我们也将学习到如何用PHP实现这种功能,而且我们还会看到如果将其有效地结合到一个数据库驱动的站点中。

最后,PHP还有一个相当强大的功能是可以很简单地将动态生成的内容很方便地作为email的信息发送出去。不论你是想要使用PHP使得访问者将你的站点的内容发送给它们的朋友,还是仅仅想提供一种方法让用户可以得到他们遗忘的口令,PHP的email函数都可以很好地实现这种功能!

PHP的服务器端包含

如果你已经在Internet上工作过一段时间,你也许接触过服务器端包含(SSI)这个术语;如果你没有接触过,你可以参看有关这个问题的Matt Mickiewicz的迷你指南。

从本质上说,SSI允许你将存储在你的Web服务器上的某一个文件的内容插入到另一个文件中去,最常见的应用是将一个网站的公用设计部分写入一个小的HTML文件当中,这个文件可以被Web页面所包含。对这个小文件的所有变动立即会影响所有包含它的文件。就象一个PHP脚本一样,Web的浏览者不需要对此有所了解,因为Web服务器会在将被请求的页面发送到浏览器之前做好所有的工作。

PHP有一个函数可以提供类似的功能。但是在包含文件中除了可以含有正式的HTML以及其它静态的内容以外,还可以含有脚本程序。让我们来看看下面这个例子:

Soylent Green is made from people! ");

?>

在上面的文件中,include-me.inc包含了一些简单的PHP代码。请注意这个文件的文件名的结尾是.inc,而不是.php。这表示这个文件与一般的Web服务器所认为的PHP脚本有所不同。这会保证这个文件只有被插入到一个.php文件中才会被执行,此外这也有助于你分辨你的PHP Web页面和PHP包含文件。

你还需要下面的文件:

Test of PHP Includes

Generating

Generating ...

Unable to load $srcurl. Static page ".

"update aborted!");

exit();

}

//将这个URL的内容读入到一个PHP变量中。

//指定我们将读取1MB的数据(超过这个数据量一般是意味着出错了)。

$htmldata = fread($dynpage, 1024*1024);

//当我们完成工作后,关闭到源“文件”的连接。

fclose($dynpage);

//打开临时文件(同时在这个过程中建立)以用来写入(注意'w'的用法).

$tempfile = fopen($tempfilename, 'w');

//处理错误

if (!$tempfile) {

echo("

Unable to open temporary file ".

"($tempfilename) for writing. Static page ".

"update aborted!");

exit();

}

//将静态页面的数据写入到临时文件中

fwrite($tempfile, $htmldata);

//完成写入后,关闭临时文件。

fclose($tempfile);

//如果到了这里,我们应该已经成功地写好了一个临时文件,

//现在我们可以用它来覆盖原来的静态页面了。

$ok = copy($tempfilename, $targetfilename);

//最后删除这个临时文件。

unlink($tempfilename);

?>

Static page successfully updated!

上面的代码看上去很令人恐怖,其实这只是因为我们在其中包含了大量的注释。删除这些注释。你会看到这段代码其实很简单。

现在,每当我们运行generateindex.php(也就是说通过一个浏览器请求这个页面),就会从index.php生成一个新刷新的index.html。通过将index.php和generateindex.php移动到一个访问有限制的目录,你可以保证只有站点管理者能够更新你的主页。将这个脚本作一下扩充,你可以生成你的站点上的所有的半动态页面,你还可以在你的内容管理系统中增加“更新主页”的连接!

如果你希望你的主页能够自动地刷新,你只需要设置你的服务器定期地运行generateindex.php(例如说,每隔一个小时)。在新的Windows 9x下,你可以使用任务管理程序(对于旧的版本,你必须使用补丁包)每隔一个小时自动运行php.exe。你只需要建立一个包含以下行的名为generateindex.bat的批处理文件。

C:PHPphp.exe C:WWWgenerateindex.php

如果必要的话,对路径和文件名进行调整,然后设置任务管理程序每隔一个小时执行一次generateindex.bat(你需要设置24个每天在固定时间运行的任务)。

在Linux下(或其它基于UNIX的平台下)你可以使用cron--一个可以在各种UNIX系统下用来定义任务和运行时间的程序来完成类似的工作。如果你对cron还不了解的话,你可以请教你熟悉的Linux专家,或者查阅你熟悉的Linux网站。

你使用cron设置任务和我们之前讨论的在Windows下的用法很类似。但是,你需要一个单机版的PHP,这不是指在第一章中编译的Apache中可导入的PHP模块。你需要对用来编译Apache模块的同一软件包中单独地进行编译。如果你需要帮助,你可以参看软件包提供的说明,也可以查阅PHP官方网站!

对于一个有经验的cron使用者来说,你只需要在你的crontab文件中增加下面的这一行:

0 0-23 * * * php /path/to/generateindex.php > /dev/null

处理文件的上载

到目前为止,这个教程中数据库驱动的站点的所有例子都是处理的文本的数据。笑话、文章、作者...所有的这些都可以完全由文本形式的字符串来表示。但是如果你在运行时,有一个在线的数字图库需要人们能够上载用数字照相机拍摄的图片,我们就需要允许访问者向我们的站点上载他们的图片,我们也需要相应的处理程序。

让我们先从基本的开始:写一个HTML表单用来供用户上载文件。在HTML中,这很简单,只需要用一个标志就行了。但是,默认情况是只有用户选择的文件名被发送了。要通过表单数据提交文件自身,我们需要在标志中增加ENCTYPE="multipart/form-data":ENCTYPE="multipart/form-data">

Select file to upload:

正如我们看到的,一个PHP脚本(fileupload.php)会处理前面的表单提交的数据。也正如你所预计的,一个名为$uploadedfile(由标志的NAME属性确定)的PHP变量会自动被建立。但是,$uploadedfile中存储的不是上载文件的内容,而是存储在Web服务器上的硬盘中的文件的文件名,这个文件被保存在TEMP环境变量所指定的目录中(例如,对于绝大多数的Windows 9x系统,这个目录将是C:WindowsTEMP)。这个文件仅仅在用来处理该表单提交的PHP脚本运行时存在,所以如果你想有什么其它用途(例如,将它存起来以供网站显示),你需要使用我们在前面提到的copy函数在其它地方做一份拷贝。

伴随着$uploadedfile,三个其它的变量也会同时被建立。$uploadedfile_name包含了文件提交前的文件名(已提交的文件将在TEMP目录中以phpx的文件名存储,这里x是一个数字),$uploadedfile_size说明了文件的大小(以字节表示),而$uploadedfile_type说明了MIME类型(例如text/plain、image/gif等等)。记住,"uploadedfile"仅仅是提交文件的INPUT标志中的NAME,实际的文件名将存在上述变量中。

你可以根据这些变量以决定是否接受一个上载的文件。例如,在我们的图库中我们仅仅只对JPEG或GIF文件感兴趣。这些文件的MIME类型应该是image/pjpeg或image/gif,所以确认上载文件的代码大致上是这样大:

if ("image/pjpeg" == $uploadedfile_type

or "image/gif" == $uploadedfile_type) {

// Handle the file...

} else {

echo("

Please submit a JPEG or GIF image file. ");

}

虽然你可以使用一个类似的技术以拒绝过大的文件(通过检查$uploadedfile_size变量),但是通常这不是一个好主意。在得到这个变量之前,这个文件已经被上载并保存在TEMP目录中。如果你试图因为磁盘容量或者是带宽的原因拒绝文件的上载,事实上那个大文件还是被上载了(尽管它们立即又被删除了),这对于你来说也许是个问题。

更好的方法是,你可以提前告诉PHP你希望可以接受的文件的大小的上限。有两个方法。第一个是调整你的php.ini文件中的upload_max_filesize设置。默认值是2MB,所以如果你想要接受更大的文件,你需要立即改变这个值。

第二个方法是在你的表单中包含一个隐含INPUT域,它的名字是MAX_FILE_SIZE,在其中你可以定义你所能接受的最大的文件的大小。出于安全的原因,这个值不能超过你的php.ini文件中的upload_max_filesize的设置,但是它提供了一种方法在不同页面中各自定义上载文件大小的上限。例如,下面的表单,只允许我们最大上载1K字节的文件(1024字节):ENCTYPE="multipart/form-data">

Select file to upload:

指定唯一的文件名

正如我们前面提到的,要保存一个上载的文件,我们需要将它拷贝到另一个目录是保存。当我们从$uploadedfile_name获取每个上载的文件的文件名时,我们不能保证不会上传两个同名的文件。在这种情况下,使用它的原名存储文件将导致新上载的文件覆盖原来上载的文件。

因为这个原因,你通过想要采用一种方法对所有上载的文件指定一个唯一的文件名。使用系统时间(它可以通过使用PHP的time函数获得),我们可以容易地取得一个其于从1/1/1970到目前的秒数的名字。但是如果两个文件恰巧在同一秒同时被上载呢?这了防止这个问题,我们在文件名中同时使用客户端的IP地址(由PHP自动存储在$REMOTE_HOST中)。因为我们不太可能同一秒从同一个IP地址接受两个文件,这个方案应该是可行的。

// Pick a file extension

if ( "image/pjpeg" == $uploadedfile_type )

$extension = ".jpg";

else

$extension = ".gif";

// The complete path/filename

$filename = "C:Uploads" . time() .

$REMOTE_HOST . $extension;

// Copy the file

if (copy($uploadedfile, $filename)) {

echo("

File stored successfully as $filename.");

} else {

echo("

Could not save file as $filename!");

}

请注意如果是在Windows下,我们必须在路径中使用双反斜杠(),因为反斜杠用来在PHP文本字符串中表示特殊字符。而在UNIX下,我们只要象通常那样使用一个斜杠(/)。

将上载的文件保存到数据库中

我们已经建立了一个访问者可以上传JPEG和GIF图象,并将其存储在我们的服务器上的系统,但是为什么不是这个教程所介绍的数据库驱动呢?如果我们这个系统就这样维持现状不变,将不得不有人负责从文件夹中收集提交的图象并手工将其添加到Web站点!回头看看第七章,在那里我们开发了一个系统使得站点的访问者可以提交笑话将将其存到数据库中,以备管理者通过,我们知道这是一种更好的方法!

MySQL有一些列类型可以用来存储二进制数据。在数据库术语中,这些列类型可以存储BLOB(二进制大对象)。然而,在一个关系型数据库中储存大的文件并不是一个好主意。尽管将所有数据放在一个地方会给我们带来方便,但是大的文件导致大的数据库,而大的数据库会导致性能的降低和太大的备份文件。

通常最好的选择是将文件名存储在数据库中。只要你记得在数据中删除记录时删除相应的文件就可以了。

PHP中的Email

Email在Internet上有着强大的影响力。不论你是想要给你的用户提供一个"what's new"周刊,还是考虑一个途径让你的用户可以获得丢失的口令,你都会用到email。PHP便得使用email非常的简单,你只需要简单地调用mail函数就可以发出信息。

在你使用mail函数发送email之前,你首先必须设置PHP的与email相关的选项。这儿是在Windows下的php.ini文件中的相关行:

[mail function]

SMTP = localhost ;仅对win32有效

sendmail_from = me@localhost.com ;仅对win32有效

;sendmail_path = ;仅对unix有效 ...

取决于你使用的是Windows还是UNIX,PHP会通过一个SMTP服务器或一个本地的sendmail系统发送email。对这些的设置不是本教程的讨论范围,你可以从其它地方找到有关这二者的大量信息。然而,如果你是在Windows上运行,有可能你的ISP已经为你提供了一个SMTP服务器。这也就是你发送信息设置你的email程序所用的服务器。将SMTP设置为那个服务器的主机名或IP地址。

sendmail_from会设置你的emails发出时默认的发出的email地址。如果你正在管理这个服务器,你可以将你的email地址放在这儿。

最后,sendmail_path在UNIX下将不会被注释(也就是说,删除这一行前面的分号),你需要将其设置为你的系统上的sendmail程序的路径和文件名。在Linux下,这通常是指/usr/sbin/sendmail。

做好这些配置后重新启动你的Web服务器,PHP将具有全部的email功能。现在在PHP中发送一个email是相当容易的:

mail("to-address@somewhere.com", "Message Subject", "This is the body of the message.");

要发送给多个收件人只需要将多个地址用逗号分开:

mail("to1@mail.net, to2@mail.net, ...", "Message Subject", "Message body");

在标题中指定From:或者Reply-To:的地址也非常简单。将其作为第四个参数带入,其中以回车-换行符分隔:

mail("to@mail.net", "Message Subject", "Message body", "From: webmaster@host.com Reply-to:admin@host.com");

与一个数据库相结合,一个邮件列表变得非常容易管理!只需要从数据库中取出地址列表并使用mail函数发送信息就行了。个人化的信息也非常简单。参看下面的例子:

// Retrieve $email and $password from the database based

// on the $username provided in a form.

mail($email, "Your Password",

"Hi there!

You just filled out a form on our Web site

indicating that you had lost your password.

As requested, we are sending it to you by

email.

username: $username

password: $password

Please record this information in a safe

place so you have it on hand for your next

visit to pingpongballs.com!

-The Webmaster.

");

如果你在在UNIX下运行,而且你没有一个本地的sendmail系统可以发送email,这也不要紧。PHP具有完善的TCP/IP网络性能,如果需要,你可以连接到一个SMTP服务器以发送信息。同样的,如果你需要在发出的信息中包含附件,PHP也可以实现这种功能。

不幸的是,内置的mail函数不支持这些特征,如果你需要它们,你将不得不从头编写你自己的email函数。WROX Press编写的"专业PHP程序设计"已经为你完成了这些工作,在该书的第17章你可以找到全部的代码。尽管这是我高度推荐的一本好书(见我的回顾),但是如果你只是想获得这项功能,你也可以不购买这本书,这个源代码你可以从WROX的网站自由地下载。

除了这两个小问题外,PHP的内置mail函数为你的Web页面发送email信息提供了令人难以相信的方便。

本文原创发布php中文网,转载请注明出处,感谢您的尊重!

PHP中阶,PHP进阶相关推荐

  1. Linux 高阶命令进阶(一)

    Linux 高阶命令进阶 (一)输出重定向 1. > :正确覆盖输出,会覆盖掉原先的文件内容 把文本写入文档中                # vim test                 ...

  2. SAP WM中阶下架策略A(Partial Pallet Quantity)

    SAP WM中阶下架策略A(Partial Pallet Quantity) SAP WM模块中,下架策略A(Partial Pallet Quantity)也比较常用.放在仓库里的物料,有零托的,有 ...

  3. SAP WM中阶Storage Type的Capacity Check – Usage check based on material

    SAP WM中阶Storage Type的Capacity Check – Usage check based on material 1, Storage type Z03激活了Capacity C ...

  4. SAP WM中阶Storage Type的Capacity Check – Check based on maximum quantity per bin in storage type.

    SAP WM中阶Storage Type的Capacity Check – Check based on maximum quantity per bin in storage type. 1, St ...

  5. SAP WM中阶Storage Type的Capacity Check – Check based on palletization according to SUT 1

    SAP WM中阶Storage Type的Capacity Check – Check based on palletization  according to SUT 1 SAP WM模块里,可以根 ...

  6. SAP WM中阶之存储类型上架策略I(Adding to existing stock)

    SAP WM中阶之存储类型上架策略I(Adding to existing stock) SAP WM模块里,有很多上架策略.Adding to existing stock是一种常用的上架策略.这种 ...

  7. SAP WM中阶之存储类型设置界面里的’Return Stock To Same Storage Bin’

    SAP WM中阶之存储类型设置界面里的'Return Stock To Same Storage Bin' 在SAP WM存储类型的配置界面里,有一个选项叫做'Return Stock to Same ...

  8. SAP WM中阶存储类型里的Full stk rmvl 字段和Return Storage type字段

    SAP WM中阶存储类型里的Full stk rmvl 字段和Return Storage type字段 SAP WM存储类型的配置里,可以配置从某个存储区域里下架的时候都是全数下架,不管需要下架的数 ...

  9. SAP WM中阶之LT25确认Group中的TO单据

    SAP WM中阶之LT25确认Group中的TO单据 SAP WM模块中,2-Step拣配中,可以为多个TR或者交货单创建Group.然后使用LX39去为Group创建TO单据,LX39里可以为这些T ...

最新文章

  1. Java自带的常用工具
  2. Python 调用 DLL
  3. php系统构建,增加知识: 如何使用PHPstudy为后端系统构建PHP源网站
  4. Elasticsearch 之(24)IK分词器配置文件讲解以及自定义词库
  5. python中continue格式_python自学(3)--for 、 while、 break、continue、字符格式化输出...
  6. 没有显示屏怎么启动服务器,中关村xp系统提示“没有启动服务器服务”如何解决...
  7. 计算机显示文本自定义130%,实训课题目
  8. java引用类型_Java引用类型
  9. Mr.J--Bootstrap使用
  10. Spring Boot Questions- Part 1
  11. 深入浅出mysql_深入浅出mysql索引
  12. 选出一个从零到五十之间的数,要求能被3整除且一位上的数为5
  13. 阿里java规范_阿里Java规范
  14. 【更新】iWebOffice2009全文批注 V10.8发布 | 附下载
  15. 阿里云短信服务SDK使用方法
  16. python语法错误检查_如何检查句子是否正确(Python中的简单语法检查)?
  17. 语雀可以导出html吗,Confluence 迁移到语雀
  18. 编译原理:了解编译原理
  19. 基于微信小程序的高校图书共享平台
  20. Python OpenCV开发MR智能人脸识别打卡系统(一、需求分析与系统设计)

热门文章

  1. casperjs 安装试用
  2. 美元加息怎么“剪羊毛”
  3. Sql Server 中锁的概念
  4. Alpha冲刺 - (5/10)
  5. java中decimalFormat格式化数值
  6. UIGraphicsBeginImageContext - 位图上下文
  7. 源码-0205-02--聊天布局
  8. tcp断开连接,4次握手,为什么wireshark 只能抓到3个包?
  9. 存储过程的优缺点 (转载)
  10. 猎豹MFC--列表控件ListControl