<?xml version="1.0" encoding="gb2312"?>
<rss version="2.0">
	<channel>
		<title>金麦网络</title>
		<link>http://www.kingmx.com</link>
		<copyright>Copyright (C) 2006 金麦网络-Kingmx.com All Rights Reserved.</copyright>
		<item>
			<title>用PHP控制FTP文件上传</title>
			<link>http://www.kingmx.com/article.php?id=17789</link>
			<pubDate>2007-10-23</pubDate>
			<description><![CDATA[
利用PHP，你总是可以有多种方式来完成某个特定的任务。我们就拿文件上传举个例子。当然了，你可以按照传统的方式来使用HTTP文件上传，把文件直接传输到Web服务器磁盘上。你还可以用更加奇异的方式上传，用FTP协议两步就完成上传：从你的本地硬盘到Web服务器，然后再到FTP服务器。

PHP在本机同时支持FTP和HTTP上传，所以你可以根据自己应用程序的设计需要进行最佳的选择。使用PHP的FTP函数进行文件传输几乎与使用传统的FTP客户端相同——你会看到连函数的名字都和标准的FTP命令类似。

关于HTTP文件上传的文章已经多得满天飞了，这就是为什么本文有必要把注意力放在基于FTP的文件上传上了（但是在后面给出的例子中，两种方式你都会看到）。要注意的是，本教程假设你已经安装好了PHP／Apache，而且HTTP文件上传和FTP的函数都已经激活了。

第一步：确信你拥有连接／上传到FTP服务器的权限

PHP 的FTP函数需要客户端－服务器连接，所以你需要在进行文件上传之前登录到目标服务器上。你的第一项任务是确信你已经拥有了完成这项任务的信任书。这一步可能看起来是理所当然的，但是你会惊奇地发现有多少开发人员忘了这么做，结果后来浪费大量的时间来解决因此而出现的问题。

你可以通过使用命令行的FTP客户端登录到目标服务器上，以检查连接状况并尝试上传一个假文件（列表A）：

列表A

$ ftp
ftp&gt; open some.host.com
Connected to some.host.com.
220 Welcome to leon FTP Server!
User: upload
331 User upload okay, need password.
Password: ***
230 Restricted user logged in.
ftp&gt; bin
200 Type okay.
ftp&gt; hash
Hash mark printing On?ftp: (2048 bytes/hash mark) .
ftp&gt; put file.bin
200 PORT command successful.
150 Opening BINARY mode data connection.
##
226 Transfer completed.
ftp: 4289 bytes sent in 0.00Seconds 4289000.00Kbytes/sec.
ftp&gt; bye
221 Goodbye.

一旦确认有相关的访问权限，你就可以登录出来。

第二步：创建上传表单

然后，创建一个简单的HTML表单，向用户询问重要的参数——FTP服务器的访问信息、服务器上传的目录，以及完整的目录和上传文件的名字。下面这个例子就是这个表单的样式（列表B）：

列表B

&lt;html&gt;
&lt;head&gt;&lt;/head&gt;
&lt;body&gt;
&lt;h2&gt;Please provide the following information:&lt;/h2&gt;

&lt;form enctype="multipart/form-data" method="post" action="upload.php"&gt;
&lt;input type="hidden" name="MAX_FILE_SIZE" value="5000000" /&gt;
Host &lt;br /&gt;
&lt;input type="text" name="host" /&gt;&lt;p /&gt;

Username &lt;br /&gt;
&lt;input type="text" name="user" /&gt;&lt;p /&gt;

Password &lt;br /&gt;
&lt;input type="password" name="pass" /&gt;&lt;p /&gt;

Destination directory &lt;br /&gt;
&lt;input type="text" name="dir" /&gt;&lt;p /&gt;

File &lt;br /&gt;
&lt;input type="file" name="file" /&gt;&lt;p /&gt;

&lt;input type="submit" name="submit" value="Upload File" /&gt;
&lt;/form&gt;

&lt;/body&gt;
&lt;/html&gt;

在这里，&lt;input type=file...&gt;元素用来生成文件选择对话框，用户通过它来选择要被上传的文件。&lt;form enctype=...&gt;元素然后就把表单数据编码成为多个部分提交，这可以让PHP更容易地识别提交的文件组件。

第三步：创建PHP上传处理程序

一旦表单被提交给了Web服务器，下一步（也是最后一步）是使用PHP的FTP函数按照用户提供的访问信任书把它传输到目标服务器上。下面就是完成上述所有工作的脚本（upload.php），见列表C：

列表C

&lt;?php

// get FTP access parameters

$host = $_POST['host'];

$user = $_POST['user'];

$pass = $_POST['pass'];

$destDir = $_POST['dir'];

$workDir = "/usr/local/temp"; // define this as per local system

// get temporary file name for the uploaded file

$tmpName = basename($_FILES['file']['tmp_name']);

// copy uploaded file into current directory

move_uploaded_file($_FILES['file']['tmp_name'], $workDir."/".$tmpName) or die("Cannot move uploaded file to working directory");

// open connection

$conn = ftp_connect($host) or die ("Cannot initiate connection to host");

// send access parameters

ftp_login($conn, $user, $pass) or die("Cannot login");

// perform file upload

$upload = ftp_put($conn, $destDir."/".$_FILES['file']['name'], $workDir."/".$tmpName, FTP_BINARY);

// check upload status

// display message

if (!$upload) {

&nbsp;&nbsp;&nbsp; echo "Cannot upload";

} else {

&nbsp;&nbsp;&nbsp; echo "Upload complete";

}

// close the FTP stream

ftp_close($conn);

// delete local copy of uploaded file

unlink($workDir."/".$tmpName) or die("Cannot delete uploaded file from working directory -- manual deletion recommended");

?&gt;

这看起来很复杂，但是事实上相当简单。下面就是实际发生的事情：

一旦表单被提交，在各种不同形式的输入字段里由用户提供的信任书被提取出来变成正常的PHP变量。关于上传文件的信息现在就可以通过PHP的专用数组$_FILES获得。 
$_FILESarray由多个子数组组成，每一个都用于一个上传文件。每个子数组的键都保存有关于相关文件的大小、MIME类型、原始名字和临时名字的信息。这些信息被move_uploaded_file()函数用来把文件从系统的临时目录传输到工作目录。你要记住更改$workDir的值，以反映你系统上的合法文件路径。 
提示：在调用move_uploaded_file()函数之前检查上传文件的类型和大小以确保它满足应用程序的上传要求是一个好习惯。例如，如果应用程序要求文件必须以ZIP格式上传，那么在这一阶段就可以（从MIME类型）检查文件是否符合要求，以保证其他格式的文件被过滤掉。

ftp_connect()和ftp_login()函数用来初始化到指定的FTP主机的连接，并使用提供的信任书登录进去。 
如果登录成功，就使用ftp_put()函数把文件从工作目录上传到用户指定的远程目录里，并把它的名字改回原来的名字。要注意的是，向ftp_put()函数加入专用的FTP_BINARY参数是要指定文件以二进制（而非ASCII）模式传输。根据ftp_put()函数返回的结果代码，用户会看到错误或者成功的消息。 
ftp_close()函数被用来结束FTP会话，而unlink()函数用来完成收尾工作，删除第二步里创建的上传文件的本地副本。 
很简单吧，不是吗？你自己试试看！
]]></description>
		</item>
		<item>
			<title>PHP调用MySQL存储过程</title>
			<link>http://www.kingmx.com/article.php?id=15237</link>
			<pubDate>2007-4-26</pubDate>
			<description><![CDATA[返回单个数据:
1.1:创建MySQL存储过程:
DELIMITER $$
DROP PROCEDURE IF EXISTS `test`.`proc_test` $$
CREATE PROCEDURE `test`.`proc_test` (out a int)
BEGIN
&nbsp;&nbsp;&nbsp; select count(*) into a from tblname;
END $$
DELIMITER ;
1.2:PHP调用:
$db-&gt;query("CALL test.proc_test(@a)");
$res = $db-&gt;query("select @a");
$row = $res-&gt;fetch_array();
echo $row['@a']; 
返回多个数据:
2.1:创建MySQL存储过程:
DELIMITER $$
DROP PROCEDURE IF EXISTS `test`.`proc_test` $$
CREATE PROCEDURE `test`.`proc_test` ()
BEGIN
&nbsp;&nbsp;&nbsp; select * from tbl_name;
END $$
DELIMITER ;
2.2:PHP调用:
$res=$db-&gt;query("CALL test.proc_test()");
while ($arr=$res-&gt;fetch_array())
{
&nbsp;&nbsp;&nbsp; echo $arr["Field"] ."&lt;br/&gt;";
}
P.S.:以上代码执行通过环境 PHP 5.X.X + MySQL 5.X.X&nbsp;&nbsp;
]]></description>
		</item>
		<item>
			<title>MySQL与存储过程</title>
			<link>http://www.kingmx.com/article.php?id=15236</link>
			<pubDate>2007-4-26</pubDate>
			<description><![CDATA[
MySQL是“世界上最为流行的开放性数据库”，至少对于MySQL Web站点会这样。但无论MySQL如此流行，很多公司都对MySQL的使用抱有抵触情绪。这种现象来自几个原因，其中有些人错误地认为开放性源代码只不过相当于小孩子的积木游戏，而另一些人认为任何免费的东西都不会是好东西。也许这些想法都是误解，然而有一种抱怨却是合理的，即与其它对应的产品不一样，比如Oracle或者 DB2，MySQL不能够支持存储过程(stored procedures)。

最新的MySQL 5.0能够支持存储过程。如果你对存储过程还没有熟悉，那么你可以认为它们只是存储在数据库服务器端的SQL命令和程序逻辑的集合。这些存储过程可以被应用程序调用，使得不同技术水平的开发人员能够建立自己的SQL。

优点 
存储过程能够允许绝大部分的数据库访问逻辑与程序逻辑分离开来。使用存储过程的其中一个间接的优点是，程序的代码变得更加小巧和容易理解。存储过程的另一优点是，SQL可以被预先编译，由此提高了程序的速度。因为存储过程包含程序逻辑，可以在数据库服务器端更多地执行更多的处理。同样，当执行一个n-tier程序时，存储过程被用于将数据层与服务层分离开来。

安全性也是存储过程的另一优点。当不能直接访问表格时，程序可以将执行优先级别分配给存储过程。不幸的是，在这时候，MySQL不支持“授予执行(GRANT EXECUTE)”。这就意味着除非程序具有访问表格的权限，否则调用访问相同表格的一个存储过程也是不行的。使用这一特性有点像在做一个很有趣的赌博。

标准 
与Oracle或者微软的相关数据库不一样，MySQL和IBM的DB2能够遵循存储程序的SQL:2003语法。在理论上这意味着，如果数据库结构相同，存储程序可以在不同数据库中使用。

可支持的SQL声明 
虽然MySQL不能支持存储程序，但它却可以完成很多任务，如表A所示。除此之外，MySQL的stored procedure documentation(存储过程文档)描述了可用于Oracle的PL/SQL和SQL Server的 T-SQL的很多兼容特性。我对存储过程支持的印象是，它执行比较缓慢，目的是避免任何影响大型软件开发工程的步骤。

表A 









声明


描述



CREATE PROCEDURE


建立一个存放在MySQL数据库的表格的存储过程。



CREATE FUNCTION


建立一个用户自定义的函数，尤其是返回数据的存储过程。



ALTER PROCEDURE


更改用CREATE PROCEDURE 建立的预先指定的存储过程，其不会影响相关存储过程或存储功能。.



ALTER FUNCTION


更改用CREATE FUNCTION 建立的预先指定的存储过程，其不会影响相关存储过程或存储功能。.



DROP PROCEDURE


从MySQL的表格中删除一个或多个存储过程。



DROP FUNCTION


从MySQL的表格中删除一个或多个存储函数。



SHOW CREATE PROCEDURE


返回使用CREATE PROCEDURE 建立的预先指定的存储过程的文本。这一声明是SQL:2003规范的一个MySQL扩展。



SHOW CREATE FUNCTION


返回使用CREATE &nbsp;FUNCTION建立的预先指定的存储过程的文本。这一声明是SQL:2003规范的一个MySQL扩展。



SHOW PROCEDURE STATUS


返回一个预先指定的存储过程的特性，包括名称、类型、建立者、建立日期、以及更改日期。这一声明是SQL:2003规范的一个MySQL扩展。



SHOW FUNCTION STATUS


返回一个预先指定的存储函数的特性，包括名称、类型、建立者、建立日期、以及更改日期。这一声明是SQL:2003规范的一个MySQL扩展。



CALL


调用一个使用CREATE PROCEDURE建立的预先指定的存储过程。



BEGIN ... END


包含一组执行的多声明。



DECLARE


用于指定当地变量、环境、处理器，以及指针。



SET


用于更改当地和全局服务器变量的值。



SELECT ... INTO


用于存储显示变量的纵列。



OPEN


用于打开一个指针。



FETCH


使用特定指针来获得下一列。



CLOSE


用于关闭和打开指针。



IF


一个An if-then-else-end if 声明。



CASE ... WHEN


一个 case声明的结构



]]></description>
		</item>
		<item>
			<title>php中计算时间差的几种方法</title>
			<link>http://www.kingmx.com/article.php?id=15235</link>
			<pubDate>2007-4-26</pubDate>
			<description><![CDATA[&nbsp;
在php中计算时间差有时候是件麻烦的事!不过只要你掌握了日期时间函数的用法那这些也就变的简单了:&nbsp;&nbsp; 
一个简单的例子就是计算借书的天数,这需要php根据每天的日期进行计算,下面就来谈谈实现这种日期计算的几种方法: 
(1) 如果有数据库就很容易了!若是MSSQL可以使用触发器!用专门计算日期差的函数datediff()便可!&nbsp;&nbsp; 
&nbsp; 若是MYSQL那就用两个日期字段的差值计算的计算结果保存在另一个数值型字段中!用时调用便可! 
(2)如果没有数据库,那就得完全用php的时间日期函数!下面主要说明之:&nbsp;&nbsp; 
&nbsp; 例:计算1998年5月3日到1999-6-5的天数:&nbsp;&nbsp; 
&lt;? $startdate=mktime("0","0","0","5","3","1998"); 
&nbsp;&nbsp; $enddate=mktime("0","0","0","6","5","1999"); 
&nbsp;&nbsp; //所得到的值为从1970-1-1到参数时间的总秒数:是整数.那么&nbsp; 

&nbsp;&nbsp; //下面的代码就好编多了: 
&nbsp; $days=round(($enddate-$startdate)/3600/24) ; 
&nbsp; echo $days; 
&nbsp; //days为得到的天数; 
&nbsp; 若mktime()中的参数缺省,那表示使用当前日期,这样便可计算从借书日期至今的天数.&nbsp;
]]></description>
		</item>
		<item>
			<title>php调用mysql存储过程和函数的方法</title>
			<link>http://www.kingmx.com/article.php?id=15234</link>
			<pubDate>2007-4-26</pubDate>
			<description><![CDATA[&nbsp;
存储过程和函数是MySql5.0刚刚引入的。关于这方面的操作在PHP里面没有直接的支持。但是由于Mysql PHP API的设计，使得我们可以在以前的PHP版本中的mysql php api中支持存储过程和函数的调用。

在php中调用存储过程和函数。

&nbsp;&nbsp;&nbsp; 1。调用存储过程的方法。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a。如果存储过程有 IN/INOUT参数，声明一个变量，输入参数给存储过程，该变量是一对，

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一个php变量（也可以不必，只是没有php变量时，没有办法进行动态输入），一个Mysql

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 变量。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b。如果存储过程有OUT变量，声明一个Mysql变量。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mysql变量的声明比较特殊，必须让mysql服务器知道此变量的存在，其实也就是执行一条mysql语句。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 入set @mysqlvar=$phpvar ;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c。使用mysql_query()/mysql_db_query()执行mysql 变量声明语句。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mysql_query("set @mysqlvar【=$pbpvar】");

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这样，在mysql服务器里面就有一个变量，@mysqlar。如果时IN参数，那么其值可以有phpar传入。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d。 如果时存储过程。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1。执行 call procedure（）语句。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 也就是mysql_query("call proceduer([var1]...)");

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2. 如果有返回值，执行select&nbsp; @ar，返回执行结果。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mysql_query("select @var)"

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接下来的操作就和php执行一般的mysql语句一样了。可以通过mydql_fetch_row()等函数获得结果。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果时函数。 直接执行 select function（） 就可以了。

&nbsp;
&nbsp;$host="localhost";
&nbsp;&nbsp;&nbsp; $user="root";
&nbsp;&nbsp;&nbsp; $password="11212";
&nbsp;&nbsp;&nbsp; $db="samp_db";
&nbsp;&nbsp;&nbsp; $dblink=mysql_connect($host,$user,$password)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; or die("can't connect to mysql");
&nbsp;mysql_select_db($db,$dblink)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; or die("can't select samp_db");
&nbsp;&nbsp;&nbsp; $res=mysql_query("set @a=$password",$dblink);
&nbsp;&nbsp;&nbsp; $res=mysql_query("call aa(@a)",$dblink);
&nbsp;&nbsp;&nbsp; $res=mysql_query("select @a",$dblink);
&nbsp;&nbsp;&nbsp; $row=mysql_fetch_row($res);
&nbsp;&nbsp;&nbsp; echo $row[0];
]]></description>
		</item>
		<item>
			<title>PHP预定义变量</title>
			<link>http://www.kingmx.com/article.php?id=15214</link>
			<pubDate>2007-4-19</pubDate>
			<description><![CDATA[
预定义变量
自 PHP 4.1.0 起，取得外部变量的首选方法是用下面提及的超全局变量。在此之前，人们要么依赖 register_globals，要么就是长长的预定义 PHP 数组（$HTTP_*_VARS）。自 PHP 5.0.0 起，长格式的 PHP 预定义变量可以通过设置 register_long_arrays 来屏蔽。 
服务器变量：$_SERVER
注: 在 PHP 4.1.0 及以后版本使用。之前的版本，使用 $HTTP_SERVER_VARS。 

$_SERVER 是一个包含诸如头信息（header）、路径（path）和脚本位置（script locations）的数组。数组的实体由 web 服务器创建。不能保证所有的服务器都能产生所有的信息；服务器可能忽略了一些信息，或者产生了一些未在下面列出的新的信息。这意味着，大量的这些变量在 CGI 1.1 规范中说明，所以应该仔细研究一下。 

这是一个“superglobal”，或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中不需要使用 global $_SERVER; 访问它，就如同使用 $HTTP_SERVER_VARS 一样。 

$HTTP_SERVER_VARS 包含着同样的信息，但是不是一个自动全局变量（注意：$HTTP_SERVER_VARS 和 $_SERVER 是不同的变量，PHP 处理它们的方式不同）。 

如果设置了 register_globals 指令，这些变量也在所有脚本中可用；也就是，分离了 $_SERVER 和 $HTTP_SERVER_VARS 数组。相关信息，请参阅安全的相关章节使用 Register Globals。这些单独的全局变量不是自动全局变量。 

或许会发现下面列出的某些 $_SERVER 元素并不可用。注意，如果以命令行方式运行 PHP，下面列出的元素几乎没有有效的（或是没有任何实际意义的）。 

“PHP_SELF” 
当前正在执行脚本的文件名，与 document root 相关。举例来说，在 URL 地址为 http://example.com/test.php/foo.bar 的脚本中使用 $_SERVER['PHP_SELF'] 将会得到 /test.php/foo.bar 这个结果。__FILE__ 常量包含当前（例如包含）文件的绝对路径和文件名。 

如果 PHP 以命令行方式运行，该变量在 PHP 4.3.0 之前无效。 

“argv” 
传递给该脚本的参数。当脚本运行在命令行方式时，argv 变量传递给程序 C 语言样式的命令行参数。当调用 GET 方法时，该变量包含请求的数据。 

“argc” 
包含传递给程序的命令行参数的个数（如果运行在命令行模式）。 

“GATEWAY_INTERFACE” 
服务器使用的 CGI 规范的版本。例如，“CGI/1.1”。 

“SERVER_NAME” 
当前运行脚本所在服务器主机的名称。如果该脚本运行在一个虚拟主机上，该名称是由那个虚拟主机所设置的值决定。 

[page]

“SERVER_SOFTWARE” 
服务器标识的字串，在响应请求时的头信息中给出。 

“SERVER_PROTOCOL” 
请求页面时通信协议的名称和版本。例如，“HTTP/1.0”。 

“REQUEST_METHOD” 
访问页面时的请求方法。例如：“GET”、“HEAD”，“POST”，“PUT”。 

注: 如果请求的方式是 HEAD，PHP 脚本将在送出头信息后中止（这意味着在产生任何输出后，不再有输出缓冲）。 

“REQUEST_TIME” 
请求开始时的时间戳。从 PHP 5.1.0 起有效。 

“QUERY_STRING” 
查询（query）的字符串（URL 中第一个问号 ? 之后的内容）。 

“DOCUMENT_ROOT” 
当前运行脚本所在的文档根目录。在服务器配置文件中定义。 

“HTTP_ACCEPT” 
当前请求的 Accept: 头信息的内容。 

“HTTP_ACCEPT_CHARSET” 
当前请求的 Accept-Charset: 头信息的内容。例如：“iso-8859-1,*,utf-8”。 

“HTTP_ACCEPT_ENCODING” 
当前请求的 Accept-Encoding: 头信息的内容。例如：“gzip”。 

“HTTP_ACCEPT_LANGUAGE” 
当前请求的 Accept-Language: 头信息的内容。例如：“en”。 

“HTTP_CONNECTION” 
当前请求的 Connection: 头信息的内容。例如：“Keep-Alive”。 

“HTTP_HOST” 
当前请求的 Host: 头信息的内容。 

“HTTP_REFERER” 
链接到当前页面的前一页面的 URL 地址。不是所有的用户代理（浏览器）都会设置这个变量，而且有的还可以手工修改 HTTP_REFERER。因此，这个变量不总是真实正确的。 

[page]

“HTTP_USER_AGENT” 
当前请求的 User-Agent: 头信息的内容。该字符串表明了访问该页面的用户代理的信息。一个典型的例子是：Mozilla/4.5 [en] (X11; U; Linux 2.2.9 i586)。也可以使用 get_browser() 得到此信息。 

“HTTPS” 
如果脚本是通过 HTTPS 协议被访问，则被设为一个非空的值。 

“REMOTE_ADDR” 
正在浏览当前页面用户的 IP 地址。 

“REMOTE_HOST” 
正在浏览当前页面用户的主机名。反向域名解析基于该用户的 REMOTE_ADDR。 

注: 必须配置 Web 服务器来建立此变量。例如 Apache 需要在 httpd.conf 中有 HostnameLookups On。参见 gethostbyaddr()。 

“REMOTE_PORT” 
用户连接到服务器时所使用的端口。 

“SCRIPT_FILENAME” 
当前执行脚本的绝对路径名。 

注: 如果脚本在 CLI 中被执行，作为相对路径，例如 file.php 或 ../file.php，$_SERVER['SCRIPT_FILENAME'] 将包含用户指定的相对路径。 

&nbsp;

“SERVER_ADMIN” 
该值指明了 Apache 服务器配置文件中的 SERVER_ADMIN 参数。如果脚本运行在一个虚拟主机上，则该值是那个虚拟主机的值。 

“SERVER_PORT” 
服务器所使用的端口。默认为“80”。如果使用 SSL 安全连接，则这个值为用户设置的 HTTP 端口。 

“SERVER_SIGNATURE” 
包含服务器版本和虚拟主机名的字符串。 

“PATH_TRANSLATED” 
当前脚本所在文件系统（不是文档根目录）的基本路径。这是在服务器进行虚拟到真实路径的映像后的结果。 

注: PHP 4.3.2 之后，PATH_TRANSLATED 在 Apache 2 SAPI 模式下不再和 Apache 1 一样隐含赋值，而是若 Apache 不生成此值，PHP 便自己生成并将其值放入 SCRIPT_FILENAME 服务器常量中。这个修改遵守了 CGI 规范，PATH_TRANSLATED 仅在 PATH_INFO 被定义的条件下才存在。 

Apache 2 用户可以使用 httpd.conf 中的 AcceptPathInfo On 来定义 PATH_INFO。 

“SCRIPT_NAME” 
包含当前脚本的路径。这在页面需要指向自己时非常有用。__FILE__ 包含当前文件的绝对路径和文件名（例如包含文件）。 

“REQUEST_URI” 
访问此页面所需的 URI。例如，“/index.html”。 

“PHP_AUTH_DIGEST” 
当作为 Apache 模块运行时，进行 HTTP Digest 认证的过程中，此变量被设置成客户端发送的“Authorization”HTTP 头内容（以便作进一步的认证操作）。 

“PHP_AUTH_USER” 
当 PHP 运行在 Apache 或 IIS（PHP 5 是 ISAPI）模块方式下，并且正在使用 HTTP 认证功能，这个变量便是用户输入的用户名。 

“PHP_AUTH_PW” 
当 PHP 运行在 Apache 或 IIS（PHP 5 是 ISAPI）模块方式下，并且正在使用 HTTP 认证功能，这个变量便是用户输入的密码。 

“AUTH_TYPE” 
当 PHP 运行在 Apache 模块方式下，并且正在使用 HTTP 认证功能，这个变量便是认证的类型。 

&nbsp;

环境变量：$_ENV
注: 在 PHP 4.1.0 及以后版本使用。之前的版本，使用 $HTTP_ENV_VARS。 

在解析器运行时，这些变量从环境变量转变为 PHP 全局变量名称空间（namespace）。它们中的许多都是由 PHP 所运行的系统决定。完整的列表是不可能的。请查看系统的文档以确定其特定的环境变量。 

其它环境变量（包括 CGI 变量），无论 PHP 是以服务器模块或是以 CGI 处理方式运行，都在这里列出了。 

这是一个“superglobal”，或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中不需要使用 global $_ENV; 来访问它，就如同使用 $HTTP_ENV_VARS 一样。 

$HTTP_ENV_VARS 包含着同样的信息，但是不是一个自动全局变量（注意：$HTTP_ENV_VARS 和 $_ENV 是不同的变量，PHP 处理它们的方式不同）。 

如果设置了 register_globals 指令，这些变量也在所有脚本中可用；也就是，分离了 $_ENV 和 $HTTP_ENV_VARS 数组。相关信息，请参阅安全的相关章节使用 Register Globals。这些单独的全局变量不是自动全局变量。 

HTTP Cookies：$_COOKIE
注: 在 PHP 4.1.0 及以后版本使用。之前的版本，使用 $HTTP_COOKIE_VARS。 

通过 HTTP cookies 传递的变量组成的数组。是自动全局变量。 

这是一个“superglobal”，或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中不需要使用 global $_COOKIE; 来访问它，就如同使用 $HTTP_COOKIE_VARS 一样。 

[page]

$HTTP_COOKIE_VARS 包含着同样的信息，但是不是一个自动全局变量（注意：$HTTP_COOKIE_VARS 和 $_COOKIE 是不同的变量，PHP 处理它们的方式不同）。 

如果设置了 register_globals 指令，这些变量也在所有脚本中可用；也就是，分离了 $_COOKIE 和 $HTTP_COOKIE_VARS 数组。相关信息，请参阅安全的相关章节使用 Register Globals。这些单独的全局变量不是自动全局变量。 

HTTP GET 变量：$_GET
注: 在 PHP 4.1.0 及以后版本使用。之前的版本，使用 $HTTP_GET_VARS。 

通过 HTTP GET 方法传递的变量组成的数组。是自动全局变量。 

这是一个“superglobal”，或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中不需要使用 global $_GET; 来访问它，就如同使用 $HTTP_GET_VARS 一样。 

$HTTP_GET_VARS 包含着同样的信息，但是不是一个自动全局变量（注意：$HTTP_GET_VARS 和 $_GET 是不同的变量，PHP 处理它们的方式不同）。 

如果设置了 register_globals 指令，这些变量也在所有脚本中可用；也就是，分离了 $_GET 和 $HTTP_GET_VARS 数组。相关信息，请参阅安全的相关章节使用 Register Globals。这些单独的全局变量不是自动全局变量。 

HTTP POST 变量：$_POST
注: 在 PHP 4.1.0 及以后版本使用。之前的版本，使用 $HTTP_POST_VARS。 

通过 HTTP POST 方法传递的变量组成的数组。是自动全局变量。 

这是一个“superglobal”，或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中不需要使用 global $_POST; 来访问它，就如同使用 $HTTP_POST_VARS 一样。 

$HTTP_POST_VARS 包含着同样的信息，但是不是一个自动全局变量（注意：$HTTP_POST_VARS 和 $_POST 是不同的变量，PHP 处理它们的方式不同）。 

如果设置了 register_globals 指令，这些变量也在所有脚本中可用；也就是，分离了 $_POST 和 $HTTP_POST_VARS 数组。相关信息，请参阅安全的相关章节使用 Register Globals。这些单独的全局变量不是自动全局变量。 

HTTP 文件上传变量：$_FILES
注: 在 PHP 4.1.0 及以后版本使用。之前的版本，使用 $HTTP_POST_FILES。 

通过 HTTP POST 方法传递的已上传文件项目组成的数组。是自动全局变量。 

这是一个“superglobal”，或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中不需要使用 global $_FILES; 来访问它，就如同使用 $HTTP_POST_FILES 一样。 

$HTTP_POST_FILES 包含着同样的信息，但是不是一个自动全局变量（请注意 PHP 是把 $HTTP_POST_FILES 和 $_FILES 这两个变量当作不同的变量来处理的）。 

如果设置了 register_globals 指令，这些变量也在所有脚本中可用；也就是，分离了 $_FILES 和 $HTTP_POST_FILES 数组。相关信息，请参阅安全的相关章节使用 Register Globals。这些单独的全局变量不是自动全局变量。 

Request 变量：$_REQUEST
注: 在 PHP 4.1.0 及以后版本使用。之前的版本，没有等价的数组。 

注: 在 PHP 4.3.0 之前，$_FILES 也被包括在 $_REQUEST 数组中。 

此关联数组包含 $_GET，$_POST 和 $_COOKIE 中的全部内容。 

这是一个“superglobal”，或者可以描述为自动全局变量。这只不过意味着它在所有的脚本中都有效。在函数或方法中不需要使用 global $_REQUEST; 来访问它。 

如果设置了 register_globals 指令，这些变量也在所有脚本中可用；也就是，分离了 $_REQUEST 数组。相关信息，请参阅安全的相关章节使用 Register Globals。这些单独的全局变量不是自动全局变量。 

Session 变量：$_SESSION
注: 在 PHP 4.1.0 及以后版本使用。之前的版本，使用 $HTTP_SESSION_VARS。 

包含当前脚本中 session 变量的数组。参阅 Session 函数文档以获得更多信息。 

这是一个“superglobal”，或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中不需要使用 global $_SESSION; 来访问它，就如同使用 $HTTP_SESSION_VARS 一样。 

$HTTP_SESSION_VARS 包含着同样的信息，但是不是一个自动全局变量（请注意 PHP 是把 $HTTP_SESSION_VARS 和 $_SESSION 这两个变量当作不同的变量来处理的）。 

[page]

如果设置了 register_globals 指令，这些变量也在所有脚本中可用；也就是，分离了 $_SESSION 和 $HTTP_SESSION_VARS 数组。相关信息，请参阅安全的相关章节使用 Register Globals。这些单独的全局变量不是自动全局变量。 

Global 变量：$GLOBALS
注: $GLOBALS 在 PHP 3.0.0 及以后版本中适用。 

由所有已定义全局变量组成的数组。变量名就是该数组的索引。 

这是一个“superglobal”，或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中不需要使用 global $GLOBALS; 来访问它。 

前一个错误消息：$php_errormsg
$php_errormsg 是包含 PHP 产生的上一错误消息内容的变量。该变量在发生错误并且 track_errors 选项打开（默认为关闭）后才有效。 

&nbsp;

&nbsp;add a note User Contributed Notes
预定义变量 
danvasile at pentest dot ro
22-Mar-2007 04:22
If you have problems with $_SERVER['HTTPS'], especially if it returns no values at all you should check the results of phpinfo(). It might not be listed at all. 
Here is a solution to check and change, if necessary, to ssl/https that will work in all cases:

&lt;?php
if ($_SERVER['SERVER_PORT']!=443) {
$sslport=443; //whatever your ssl port is
$url = "https://". $_SERVER['SERVER_NAME'] . ":" . $sslport . $_SERVER['REQUEST_URI'];
header("Location: $url");
}
?&gt;

Of course, this should be done before any html tag or php echo/print. 
bosmeew at gmail dot com
18-Feb-2007 10:43
To get the server address, you can use $_SERVER['SERVER_ADDR']. However, this only works when your PHP process is running on a webserver, not when running PHP as CLI. Here is a function which will also return the server address when running on linux (eth0 is hardcoded as the network interface, modify if necessary).

&lt;?php

function getServerAddress() {
&nbsp;&nbsp;&nbsp; if($_SERVER['SERVER_ADDR']) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return $_SERVER['SERVER_ADDR'];
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; $ifconfig = shell_exec('/sbin/ifconfig eth0');
&nbsp;&nbsp;&nbsp; preg_match('/addr:([\d\.]+)/',$ifconfig,$match);
&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; return $match[1];
}

?&gt; 
borg at sven-of-nine dot de
30-Jan-2007 07:22
Simple function to determine if a visitor is an agent or not

function isbot($agent="")
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp; //Handfull of Robots
&nbsp;&nbsp;&nbsp; $bot_array&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =array("jeevesteoma",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "msnbot",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "slurp",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "jeevestemoa",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "gulper",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "googlebot",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "linkwalker",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "validator",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "webaltbot",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "wget");
&nbsp;&nbsp;&nbsp; //no agent given =&gt; read from globals
&nbsp;&nbsp;&nbsp; if ($agent=="")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @$agent=$_SERVER["HTTP_USER_AGENT"];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; //replace all but alpha
&nbsp;&nbsp;&nbsp; $agent=strtolower(preg_replace("/[^a-zA-Z _]*/","",$agent));
&nbsp;&nbsp;&nbsp; //check für intersections
&nbsp;&nbsp;&nbsp; return((BOOL)count(array_intersect(explode(" ",$agent),$bot_array)));
&nbsp;&nbsp;&nbsp; } 
Joe Marty
25-Jan-2007 03:53
I think it is very important to note that PHP will automatically replace dots ('.') AND spaces (' ') with underscores ('_') in any incoming POST or GET (or REQUEST) variables.

This page notes the dot replacement, but not the space replacement:
http://us2.php.net/manual/en/language.variables.external.php

The reason is that '.' and ' ' are not valid characters to use in a variable name.&nbsp; This is confusing to many people, because most people use the format $_POST['name'] to access these values.&nbsp; In this case, the name is not used as a variable name but as an array index, in which those characters are valid.

However, if the register_globals directive is set, these names must be used as variable names.&nbsp; As of now, PHP converts the names for these variables before inserting them into the external variable arrays, unfortunately - rather than leaving them as they are for the arrays and changing the names only for the variables set by register_globals.

If you want to use:
&lt;input name="title for page3.php" type="text"&gt;

The value you will get in your POST array, for isntance would be:
$_POST['title_for_page3_php'] 
NeoSmart Technologies
18-Nov-2006 10:22
The *only* way to make Request_URI work as a 100% Apache-Compliant server variable on IIS/Windows is to use an Isapi Filter - as documented at http://neosmart.net/blog/archives/291 . The various steps mentioned below *completely* fail when a rewrite engine is employed, since IIS will *never* return a non-existent path (i.e. the actual pretty-URI used) via its server variables. 

This also applies to accessing index.php via a folder.
For instance, calls made to /folder/ will appear as /folder/index.php and not /folder/.

The fix is to use the ISAPI filter provided at http://neosmart.net/blog/archives/291

You don't have to modify any of the actual scripts once this filter is in place - it automatically intercepts calls to REQUEST_URI and replaces them with the actual user-entered path. 
me at tommygeorge dot com
10-Nov-2006 12:59
I'm sure this is elsewhere, but since 'chris dot chaudruc at gmail dot com' posted his example, I thought I would share a quick function I use to force HTTPS protocol on a page, without having to know the scripts name...

[page]

&lt;?php
function ForceHTTPS() 
{
&nbsp;&nbsp;&nbsp; if( $_SERVER['HTTPS'] != "on" )&nbsp; 
&nbsp;&nbsp;&nbsp; { 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $new_url = "https://" . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; header("Location: $new_url");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit;
&nbsp;&nbsp;&nbsp; } 
}
?&gt;

Correct me if part of this doesn't work right. I've always used *nix based servers for PHP, so I might not be aware of certain windows limitations. Thanks. 
Uili - e-info(at)tunenami.com
25-Oct-2006 06:34
Andy Staudacher may have addressed this in his bug fix but just for clarifacation when reading a cookie $_COOKIE reads only the most accurate domain including sub domain. If you have cookies for .bar.com and foo.bar.com and the user is at foo.bar.com $_COOKIE only returns the cookie data from foo.bar.com but if the user is at www.bar.com the data from .bar.com will be read if there is no cookie for www.bar.com. 
dlyaza aT yahoo DOT com
23-Oct-2006 03:33
Get Real IP Address; If some one Know More than below, let us to see

if (getenv('HTTP_CLIENT_IP')) {
$IP = getenv('HTTP_CLIENT_IP');
}
elseif (getenv('HTTP_X_FORWARDED_FOR')) {
$IP = getenv('HTTP_X_FORWARDED_FOR');
}
elseif (getenv('HTTP_X_FORWARDED')) {
$IP = getenv('HTTP_X_FORWARDED');
}
elseif (getenv('HTTP_FORWARDED_FOR')) {
$IP = getenv('HTTP_FORWARDED_FOR');
}
elseif (getenv('HTTP_FORWARDED')) {
$IP = getenv('HTTP_FORWARDED');
}
else {
$IP = $_SERVER['REMOTE_ADDR'];
} 
seanhickey at gmail dot com
20-Sep-2006 05:46
Note that class objects will not be in the $GLOBALS array until *after* the classe's constructor returns.

&lt;?php
class A
{
&nbsp;&nbsp;&nbsp; public function __construct()
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var_dump($GLOBALS);
&nbsp;&nbsp;&nbsp; }
}

$a = new A;
var_dump($GLOBALS);
?&gt;

The first var_dump() inside the __construct() method will not contain the value of $a, while the second one will. 
Alexander Hars
19-Sep-2006 05:16
If you want to use a form with multiple checkboxes (e.g. one per row) and assign the same name to each checkbox then the name needs to end with []. This tells PHP to put all checked values into an array variable. 
For example:
&lt;input type="checkbox" name="id[]" value="value_1"&gt;
&lt;input type="checkbox" name="id[]" value="value_2"&gt;
..
&lt;input type="checkbox" name="id[]" value="value_x"&gt;

You can now retrieve all values by using: 
&nbsp;&nbsp; $values = $_POST['id'];

If the name does not end with [], then only a single value will be available via the $_POST variable even if the user checks several checkboxes. 
trevor
09-Aug-2006 01:49
I needed to do the exact same thing as jwl007 (sort by clicking links) but I needed it to append the variable to the query string if it didn't already exist. Here's the function I'm using:

&lt;?php
function setGetVar($var, $val){
&nbsp;&nbsp;&nbsp; $request_uri = $_SERVER["REQUEST_URI"];
&nbsp;&nbsp;&nbsp; if(strstr($request_uri, $var)) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return preg_replace("/$var=[\\d\\w]*/", "$var=$val", $request_uri);
&nbsp;&nbsp;&nbsp; } elseif(strstr($request_uri, "?")) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return $request_uri . "&amp;" . $var . "=" . $val;
&nbsp;&nbsp;&nbsp; } else {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return $request_uri . "?" . $var . "=" . $val;
&nbsp;&nbsp;&nbsp; }
}
?&gt;

&lt;a href="&lt;?php echo setGetVar("orderby", "lname"); ?&gt;"&gt;Sort by Last Name&lt;/a&gt;
&lt;a href="&lt;?php echo setGetVar("orderby", "fname"); ?&gt;"&gt;Sort by First Name&lt;/a&gt; 
jmurphy at hsdirect dot co dot uk
26-Jul-2006 10:17
As above the $_SERVER['request_uri']

is replaced in windows iis with

$_SERVER['script_name'] 
jameslporter at gmail dot com
06-May-2006 03:19
Refer to CanonicalName if you are not getting the ServerName in the $_SERVER[SERVER_NAME] variable....This was a pain to figure out for me...now it works as expected by turning canonical naming on.

http://www.apacheref.com/ref/http_core/UseCanonicalName.html 
tchamp
26-Apr-2006 10:24
Be careful with HTTP_HOST behind a proxy server.&nbsp;&nbsp; Use these instead.
[HTTP_X_FORWARDED_FOR] 
[HTTP_X_FORWARDED_HOST] 
[HTTP_X_FORWARDED_SERVER]

In my situation, I used [HTTP_X_FORWARDED_SERVER] in place of [HTTP_HOST] in order get the machine and hostname (www.myurl.com) 
Ben XO
14-Apr-2006 09:18
So you have an application in your web space, with a URL such as this:

http://&lt;host&gt;/&lt;installation_path&gt;/

and pages such as

http://&lt;host&gt;/&lt;installation_path&gt;/subfolder1/subfolder2/page.php

You have a file called config.php in &lt;installation_path&gt; which is include()d by all pages (in subfolders or not).

How to work out &lt;installation_path&gt; without hard-coding it into a config file? 

[page]

&lt;?php

// this is config.php, and it is in &lt;installation_path&gt;
// it is included by &lt;installation_path&gt;/page.php
// it is included by &lt;installation_path&gt;/subfolder/page2.php
// etc

$_REAL_SCRIPT_DIR = realpath(dirname($_SERVER['SCRIPT_FILENAME'])); // filesystem path of this page's directory (page.php)
$_REAL_BASE_DIR = realpath(dirname(__FILE__)); // filesystem path of this file's directory (config.php)
$_MY_PATH_PART = substr( $_REAL_SCRIPT_DIR, strlen($_REAL_BASE_DIR)); // just the subfolder part between &lt;installation_path&gt; and the page

$INSTALLATION_PATH = $_MY_PATH_PART
&nbsp;&nbsp;&nbsp; ? substr( dirname($_SERVER['SCRIPT_NAME']), 0, -strlen($_MY_PATH_PART) )
&nbsp;&nbsp;&nbsp; : dirname($_SERVER['SCRIPT_NAME'])
; // we subtract the subfolder part from the end of &lt;installation_path&gt;, leaving us with just &lt;installation_path&gt; :)

?&gt; 
todd dot kisov at yahoo dot com
03-Apr-2006 05:11
To convert query string parameter values ($_GET, $_REQUEST), which include escaped Unicode values resulting from applying the javascript "escape" function to a Unicode string (%uNNNN%uNNNN%uNNNN) fast and simple is to use PECL JSON extension:

function JavaScript_Unicode_URL_2_Str($js_uni_str) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $res = preg_replace('/%u([[:alnum:]]{4})/', '\\u\1', $js_uni_str);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $res = str_replace('"', '\"', $res); // if in str "
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $res = json_decode('["'.$res.'"]'); // JavaScrip array with string element
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $res = $res[0];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $res = iconv('UTF-8', ini_get('default_charset'), $res);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return $res;
&nbsp;&nbsp;&nbsp; } 
01-Apr-2006 01:56
I was unable to convince my hosting company to change their installation of PHP and therefore had to find my own way to computer $_SERVER["DOCUMENT_ROOT"].&nbsp; I eventually settled on the following, which is a combination of earlier notes (with some typos corrected):

&lt;?php
if ( ! isset($_SERVER['DOCUMENT_ROOT'] ) )
&nbsp; $_SERVER['DOCUMENT_ROOT'] = str_replace( '\\', '/', substr(
&nbsp;&nbsp;&nbsp; $_SERVER['SCRIPT_FILENAME'], 0, 0-strlen($_SERVER['PHP_SELF']) ) );
?&gt; 
mjs at beebo dot org
30-Mar-2006 05:24
Note that PHP_SELF will not be equal to REQUEST_URI under Apache if mod_rewrite has been used to move one URL to another--PHP_SELF will contain the rewritten address, and REQUEST_URI will contain the URL the user sees in their browser. 
adam3000 at gmail dot com
16-Mar-2006 02:30
I was trying to find an alternative to $_SERVER['REQUEST_URI'] for a Windows NT set up and the ones below didn't really work for me so here's my solution using eustf at hotmail dot com's suggestion of $_SERVER['PHP_SELF']:

// if 'REQUEST_URI' isn't available then ...
if(!isset($_SERVER['REQUEST_URI'])) {
&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; // ... set my own request url and ...
&nbsp;&nbsp;&nbsp; $temp_request_url = $_SERVER['PHP_SELF'];
&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; // ... test for and add url variables to my request url ...
&nbsp;&nbsp;&nbsp; if (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $temp_request_url .= (strpos($updateGoTo, '?')) ? "&amp;" : "?";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $temp_request_url .= $HTTP_SERVER_VARS['QUERY_STRING'];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

} else {
&nbsp;&nbsp;&nbsp; // ... otherwise use the regular 'REQUEST_URI'
&nbsp;&nbsp;&nbsp; $temp_request_url = $_SERVER['REQUEST_URI'];
} 
Aardvark
08-Mar-2006 05:35
$_GET may not handle query string parameter values which include escaped Unicode values resulting from applying the JavaScript "escape" function to a Unicode string.
To handle this the query parameter value can be obtained&nbsp; using a function such as:

function getQueryParameter ($strParam) {
&nbsp; $aParamList = explode('&amp;', $_SERVER['QUERY_STRING']);
&nbsp; $i = 0;
&nbsp; while ($i &lt; count($aParamList)) {
&nbsp;&nbsp;&nbsp; $aParam = split('=', $aParamList[$i]);
&nbsp;&nbsp;&nbsp; if ($strParam == $aParam[0]) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return $aParam[1];
&nbsp;&nbsp;&nbsp; } 
&nbsp; }
&nbsp; return "";
}

or by directly building an array or query string values and then processing the parameter string using a function such as the "unescape" function which can be found at http://www.kanolife.com/escape/2006/03/unicode-url-escapes-in-php.html (or http://www.kanolife.com/escape/ for related info). 
justin dot (nospam)george at gmail dot com
01-Mar-2006 04:00
Note that it's a very, very bad idea to append to global variables in a loop, unless you really, really mean to do so in a global context. I just a while ago hung my server with a snippet of code like this:

&lt;?php
$host&nbsp; = $_SERVER['HTTP_HOST'];
$uri&nbsp; = rtrim($_SERVER['PHP_SELF'], "/\\");

&nbsp;&nbsp; 
$GLOBALS['SITE_ROOT'] = "http://$host$uri";

while ($i &lt; somenumber)
readfile($GLOBALS['SITE_ROOT'] = $GLOBALS['SITE_ROOT'] . '/this/file.php');
$i++
}
?&gt;

While it is an entertaining and unusual method of creating very long URLs and breaking servers, it's a pretty awesomely bad idea 

(Especially considering that the script in question ran concurrently with others of it's type, so the value in $GLOBALS['SITE_ROOT'] was unknown.) 
nathan
23-Feb-2006 12:05
Also on using IPs to look up country &amp; city, note that what you get might not be entirely accurate.&nbsp; If their ISP is based in a different city or province/state, the IPs may be owned by the head office, and used across several areas.&nbsp; 
You also have rarer situations where they might be SSHed into another server, on the road, at work, at a friend's...&nbsp; It's a nice idea, but as the example code shows, it should only be used to set defaults. 
geza at turigeza dot com
11-Feb-2006 09:13
Above the manual says

'$_REQUEST is an associative array consisting of the contents of $_GET, $_POST, and $_COOKIE.'
However 
$_REQUEST doesn't always contain the same elements as

$_GET+$_POST+$_REQUEST;

Basically if you add an element to the $_POST array that element does not automatically get added to REQUEST as well. It's easy to understand why :)

&lt;?php 
$_POST['geza'] = 'geza';
$_GET['bela'] = 'bela';

echo '&lt;pre&gt;';
print_r($_POST);
print_r($_GET);
print_r($_REQUEST);
echo '&lt;/pre&gt;';
?&gt;

will output this
Array
(
&nbsp;&nbsp;&nbsp; [geza] =&gt; geza
)
Array
(
&nbsp;&nbsp;&nbsp; [bela] =&gt; bela
)
Array
(
) 
marsh at NOSPAM-TAKETHATSPAMMER dot uri
20-Jan-2006 12:05
The solution advanced by info at meshkaat dot com does not work correctly on machines with IIS configured to use
a virtual directory as the launch point. The address strings for $_SERVER['SCRIPT_FILENAME'] and $_SERVER['PHP_SELF'] will not necessarily have the same name for the highest level directory in $_SERVER['PHP_SELF'], and therefore this solution will not return the proper value. 
marsh at NOSPAM-TAKETHATSPAMMER dot uri dot edu
12-Jan-2006 11:57
Under Windows XP SP2 and IIS, $_SERVER('x') returns a path using forward slash '/' as the separator, where x is:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PHP_SELF, SCRIPT_NAME

These arguments, however, all return a path using backward slash, '\' as the separator:

&nbsp; __FILE__, SCRIPT_FILENAME, and DOCUMENT_ROOT (if you use one of the methods mentioned previously).

Also note that if the name of the last directory in the document root includes a space, the methods described above for setting DOCUMENT_ROOT will return a value that drops the everything past the space. 
Andy Staudacher, gmx.ch add ast before @
20-Dec-2005 09:02
The following code is licensed under the GPL and it is from the gallery.menalto.com project.

[page]

&lt;?php
&nbsp;&nbsp;&nbsp; /**
&nbsp;&nbsp;&nbsp;&nbsp; * Fix the superglobal $_COOKIE to conform with RFC 2965
&nbsp;&nbsp;&nbsp;&nbsp; *
&nbsp;&nbsp;&nbsp;&nbsp; * We don't use $_COOKIE[$cookiename], because it doesn't conform to RFC 2965 (the
&nbsp;&nbsp;&nbsp;&nbsp; * cookie standard), i.e. in $_COOKIE, we don't get the cookie with the most specific path for
&nbsp;&nbsp;&nbsp;&nbsp; * a given cookie name, we get the cookie with the least specific cookie path.
&nbsp;&nbsp;&nbsp;&nbsp; * This function does it exactly the other way around, to a) fix our cookie/login problems and
&nbsp;&nbsp;&nbsp;&nbsp; * to b) conform with the RFC.
&nbsp;&nbsp;&nbsp;&nbsp; * The PHP bug was already fixed in spring 2005, but we will have to deal with broken PHP
&nbsp;&nbsp;&nbsp;&nbsp; * versions for a long time. See http://bugs.php.net/bug.php?id=32802.
&nbsp;&nbsp;&nbsp;&nbsp; *
&nbsp;&nbsp;&nbsp;&nbsp; * Fixes also another PHP cookie bug. PHP doesn't expect the cookie header to have
&nbsp;&nbsp;&nbsp;&nbsp; * quoted-strings, but they are perfectly legal according to RFC 2965.
&nbsp;&nbsp;&nbsp;&nbsp; *
&nbsp;&nbsp;&nbsp;&nbsp; * The third bug fixed here is an MS Internet Explorer (IE) bug. When using default cookie
&nbsp;&nbsp;&nbsp;&nbsp; * domains (no leading dot, don't set the domain in set-cookie), IE is supposed to return only
&nbsp;&nbsp;&nbsp;&nbsp; * cookies that have the exact request-host as their domain.
&nbsp;&nbsp;&nbsp;&nbsp; * Example: Cookies stored in the browser with cookie domains: .example.com, .www.example.com,
&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; example.com, www.example.com
&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The request-host is www.example.com. Thus, IE should return all those cookies but
&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the example.com cookie, because it's a default domain cookie and it doesn't match
&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exactly the request-host. But IE returns the example.com cookie too.
&nbsp;&nbsp;&nbsp;&nbsp; * As MS decided that it returns the cookie with the best domain-match first (unspecified in
&nbsp;&nbsp;&nbsp;&nbsp; * RFC 2965), this wouldn't be a problem if PHP didn't select the last cookie in the
&nbsp;&nbsp;&nbsp;&nbsp; * HTTP_COOKIE header. But with fixCookieVars(), this case is also fixed.
&nbsp;&nbsp;&nbsp;&nbsp; *
&nbsp;&nbsp;&nbsp;&nbsp; * This function reevaluates the HTTP Cookie header and populates $_COOKIE with the correct
&nbsp;&nbsp;&nbsp;&nbsp; * cookies. We fix only non-array and non '[', ']' containing cookies for simplicity. To fix
&nbsp;&nbsp;&nbsp;&nbsp; * our login problem, we'd have to fix only the GALLERYSID cookie anyway.
&nbsp;&nbsp;&nbsp;&nbsp; *
&nbsp;&nbsp;&nbsp;&nbsp; * @param boolean force the reevaluation of the HTTP header string Cookie
&nbsp;&nbsp;&nbsp;&nbsp; * @param boolean unset static variable for testability
&nbsp;&nbsp;&nbsp;&nbsp; */
&nbsp;&nbsp;&nbsp; function fixCookieVars($force=false, $unset=false)
?&gt;
The source code can be found at:
http://cvs.sourceforge.net/viewcvs.py/gallery/gallery2/
modules/core/classes/GalleryUtilities.class?rev=1.146&amp;view=markup 
info at meshkaat dot com
06-Dec-2005 09:03
How to get $_SERVER["DOCUMENT_ROOT"] on IIS :

if(!isset($_SERVER["DOCUMENT_ROOT"]))
{$_SERVER["DOCUMENT_ROOT"]=substr($_SERVER['SCRIPT_FILENAME'] , 0 , -strlen($_SERVER['PHP_SELF'])+1 );
}

it simply works! 
chris at vault5 dot com
30-Nov-2005 11:17
Since $_SERVER['DOCUMENT_ROOT'] is not always present, the following will provide it where $_SERVER dosen't.

&lt;?php
function resolveDocumentRoot() {
&nbsp;&nbsp;&nbsp; $current_script = dirname($_SERVER['SCRIPT_NAME']);
&nbsp;&nbsp;&nbsp; $current_path&nbsp;&nbsp; = dirname($_SERVER['SCRIPT_FILENAME']);
&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; /* work out how many folders we are away from document_root
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by working out how many folders deep we are from the url.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this isn't fool proof */
&nbsp;&nbsp;&nbsp; $adjust = explode("/", $current_script);
&nbsp;&nbsp;&nbsp; $adjust = count($adjust)-1;
&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; /* move up the path with ../ */
&nbsp;&nbsp;&nbsp; $traverse = str_repeat("../", $adjust);
&nbsp;&nbsp;&nbsp; $adjusted_path = sprintf("%s/%s", $current_path, $traverse);

&nbsp;&nbsp;&nbsp; /* real path expands the ../'s to the correct folder names */
&nbsp;&nbsp;&nbsp; return realpath($adjusted_path);&nbsp;&nbsp;&nbsp; 
}

?&gt;

It counts the number of folders down the path we are in the URL, then moves that number of folders up the current path... end result should be the document root :)

It wont work with virtual folders or in any situation where the folder in the URL dosen't map to a real folder on the disk (like when using rewrites). 
lorenpr at gmail dot com
02-Nov-2005 07:04
Here's a simple function that has proven reliable for me in checking if a user has refreshed the current page on a website.

function pageRefreshed()
{
&nbsp; if($_SERVER['HTTP_CACHE_CONTROL'] == 'max-age=0') 
&nbsp;&nbsp;&nbsp;&nbsp; return true;

&nbsp;&nbsp; return false;
} 
webmaster at eclipse dot org
11-Oct-2005 11:01
In response to tobias at net-clipping dot de

It is not an Apache bug.&nbsp; Please read http://httpd.apache.org/docs/2.1/mod/core.html#errordocument carefully (2.1 version here, 2.0 and 1.x is similar).&nbsp; 

In short, if your ErrorDocument start with http:// Apache sends a redirect (302) to the error document, hence losing your original referer. If your ErrorDocument points to a relative path, 404 is maintained and so are your variables.

From the Apache manual:

[page]

"Note that when you specify an ErrorDocument&nbsp; that points to a remote URL (ie. anything with a method such as http in front of it), Apache will send a redirect to the client to tell it where to find the document, even if the document ends up being on the same server. This has several implications, the most important being that the client will not receive the original error status code, but instead will receive a redirect status code. This in turn can confuse web robots and other clients which try to determine if a URL is valid using the status code. In addition, if you use a remote URL in an ErrorDocument 401, the client will not know to prompt the user for a password since it will not receive the 401 status code. Therefore, if you use an ErrorDocument 401 directive then it must refer to a local document."

D. 
drew dot griffiths at clare dot net
30-Sep-2005 11:51
Re: You can take advantage of 404 error to an usable redirection using REQUEST_URI ...

Whilst this is effective, a line in the .htaccess such as:

RewriteEngine On
RewriteRule ^profiles/([A-Za-z0-9-]+) showprofile.php?profile=$1 [L,NC,QSA]

will throw the requested profile in a variable $profile to the showprofile.php page.&nbsp; 

You can further enhance the url (e.g http://servername/profiles/Jerry/homeaddress/index.htm) and the second variable value homeaddress becomes available in $url_array[3] when used below $url_array=explode("/",$_SERVER['REQUEST_URI']);&nbsp;&nbsp; 

Hope this helps - Works well for me

Drew 
jeromenelson at gmail dot com
19-Sep-2005 06:56
You can take advantage of 404 error to an usable redirection using REQUEST_URI ...

For example the following program can retrieve the information for the 'search_string', for a given URI:&nbsp; http://servername/profiles/search_string, even though there's no such path.
Do the following steps..

Step 1: Edit Apache config:&nbsp; set
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ErrorDocument 404 "/missing.php"&nbsp; 
Step 2: Write the missing.php as follows ...

&lt;?
$mainPath = "/profiles/";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Example: http://servername/profiles/search_string
$mpLength = strlen( $mainPath&nbsp; );&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
$request_uri = $_SERVER['REQUEST_URI'];

if ( $mainPath != substr($request_uri,0,$mpLength) ) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Check if the given URI is valid
&nbsp;&nbsp;&nbsp; echo "404 Page Not Found !";
&nbsp;&nbsp;&nbsp; exit();
}

$name = substr ($request_uri , $mpLength ) ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Extract the string to be searched

echo "You have searched for the profile of Mr. $name";

/** Here you can write the code to retrieve and display
&nbsp;&nbsp;&nbsp;&nbsp; the $name's&nbsp; information from the database
*/
?&gt;

Step 3: Now try http://servername/profiles/Jerry
&nbsp;&nbsp;&nbsp; (of course, there shouldn't be a file/folder in the server like "DOCROOT/profiles/Jerry" )

&nbsp;&nbsp;&nbsp;&nbsp; output: You have searched for the profile of Mr. Jerry

God Bless You! 
Angelina Bell
04-Aug-2005 11:55
Warning:
$_SERVER['PHP_SELF'] and $_SERVER['SCRIPT_NAME'] may not always be set correctly.
Some web hosts implement php as a CGI in such a way that they can turn it on or off for each virtual domain.&nbsp; Several $_SERVER and $_ENV variable values may be incorrect for documents in subdirectory subdomains of these virtual domains.

An include-file function or constant, instead of PHP_SELF or some other predefined variable throughout a website, will make it easier to "fix" an entire website in case something changes.
&lt;?php
function true_url_path() {
// Pick the predefined variable that works on your server
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return $_ENV['SCRIPT_URL'];
}
?&gt;
Or
&lt;?php
// Pick the predefined variable that works on your server
define("TRUE_URL_PATH", $_ENV['SCRIPT_URL']);
?&gt; 
Gregory Boshoff
31-Jul-2005 05:41
$_SERVER['QUERY_STRING'] 

Does not contain XHTML 1.1 compliant ampersands i.e. &amp;amp;

So you will need to do something like this if you are to use $_SERVER['QUERY_STRING'] in URL's.

//&nbsp; XHTML 1.1 compliant ampersands 
$_SERVER['QUERY_STRING'] = 
str_replace(array('&amp;amp;', '&amp;'), array('&amp;', '&amp;amp;'), 
$_SERVER['QUERY_STRING']); 
New York PHP
24-Jul-2005 09:59
Warning: $_SERVER['PHP_SELF'] can include arbitrary user input. The documentation should be updated to reflect this.

The request "http://example.com/info.php/attack%20here" will run /info.php, but in Apache $_SERVER['PHP_SELF'] will equal "/info.php/attack here". This is a feature, but it means that PHP_SELF must be treated as user input.

The attack string could contain urlencoded HTML and JavaScript (cross-site scripting) or it could contain urlencoded linebreaks (HTTP response-splitting).

The use of $_SERVER['SCRIPT_NAME'] is recommended instead. 
eustf at hotmail dot com
21-Jul-2005 11:05
REQUEST_URI not defined on Windows XP and IIS 5.1
I have seen different script on the web and in this list but they don't work fully. This one seems to work:

if(!isset($_SERVER['REQUEST_URI'])) {
&nbsp; $arr = explode("/", $_SERVER['PHP_SELF']);
&nbsp; $_SERVER['REQUEST_URI'] = "/" . $arr[count($arr)-1];
&nbsp; if ($_SERVER['argv'][0]!="")
&nbsp;&nbsp;&nbsp; $_SERVER['REQUEST_URI'] .= "?" . $_SERVER['argv'][0];
} 
daniel at softel dot jp
16-Jul-2005 02:43
Note that $php_errormsg may contain a newline character. This can be problematic if you are trying to output it with a JavaScript "alert()" for example. 
andy dot gajetzki at gmail dot com
06-Jul-2005 09:22
I wanted to be able to embed a variable in the path. This is useful when, for example, images are rendered on the fly and you would like them to have different urls. 

Here is an illustration:

www.somesite.com/image.php/IMAGETEXTHERE

This would return an image with the text after "image.php/" contained in it. 

I could not recall the name of this feature, so I made a work-around in PHP...

&lt;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
function getPathVariables() {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sPathPS = $_SERVER[PHP_SELF];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sPathFS = __FILE__;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $aPathPS = array_reverse(explode("/", $sPathPS));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $aPathFS = array_reverse(explode("/", $sPathFS));

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $aImageArgs = array();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $x = 0;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while ( $aPathPS[$x] != $aPathFS[$x] &amp;&amp; $aPathPS[$x] != $aPathFS[0] ) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; array_unshift($aImageArgs, $aPathPS[$x])&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $x++;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return $aImageArgs;

}
?&gt;

This function will return an array containing each "/" delimited portion of the path after the script name itself. 
notes at arbee dot co dot uk
27-Jun-2005 10:14
Note that $_SERVER['QUERY_STRING'] behaves differently under IIS/Apache.

[page]

In Apache (at least on Windows) it is ALWAYS set - if no query string was specified in the URL, $_SERVER['QUERY_STRING'] is initialised as an empty string.

In IIS, if no query string is included in the URL, $_SERVER['QUERY_STRING'] is NOT SET, so trying to access it without checking for its existence will generate notices. 
koerner-familie at t-online dot de
21-Jun-2005 09:52
If you want to make a copy of $BLOBALS (e.g. to test whether which tariables were changed during script-runtime, 
&lt;?php $___debug_var_dump = $GLOBALS; ?&gt;
will _NOT_ make a copy in PHP4 (tested with 4.3.11). Use 
&lt;?php $___debug_var_dump = array_merge($GLOBALS, array()); ?&gt; instead, but ONLY for testing purpose.
Best regards, Peter 
purplebz at hotmail dot com
19-Jun-2005 04:35
How to get $_SERVER['REQUEST_URI'] on IIS (WinXP):

if ( empty($_SERVER['REQUEST_URI']) ) {
&nbsp;&nbsp; $arr = explode("/", $_SERVER['PHP_SELF']);
&nbsp;&nbsp; $_SERVER['REQUEST_URI'] = $arr[count($arr)-1];
} 
xangelusx at hotmail dot com
14-Jun-2005 04:03
A note about the QUERY_STRING variable when using IIS:

I have found that IIS does not handle large query strings gracefully when passed from PHP. In addition to truncating them to around 1024 kb, I have seen IIS actually add data from other server variables to the end of the truncated data. 

This occurred on Windows 2000 server running IIS 5.0 and PHP 4.3.8.&nbsp; The problem did not occur when handled by Apache, even on another Windows server.

Note: I realize passing this much data is best accomplished using the POST method, which would avoid this problem all together. I'm merely detailing a problem that I came across.

I have created a page that includes the (very long) query string that was used and some of the results that I saw while testing. It can be viewed at http://www.csb7.com/test/php_iis_qs_limit/. I didn't want to include it here as it would stretch the page out significantly.

~Chris Bloom 
mfyahya at gmail dot com
07-Jun-2005 09:33
If you use Apache's redirection features for custom error pages or whatever, the following Apache's REDIRECT variables are also available in $_SERVER:
$_SERVER['REDIRECT_UNIQUE_ID]' 
$_SERVER['REDIRECT_SCRIPT_URL]' 
$_SERVER['REDIRECT_SCRIPT_URI]' 
$_SERVER['REDIRECT_SITE_ROOT]' 
$_SERVER['REDIRECT_SITE_HTMLROOT]' 
$_SERVER['REDIRECT_SITE_CGIROOT]' 
$_SERVER['REDIRECT_STATUS]' 
$_SERVER['REDIRECT_QUERY_STRING]' 
$_SERVER['REDIRECT_URL]' 

I'm not sure if this is a complete list though 
mp at wds-tech dot de
02-Jun-2005 03:12
Also aviable is the $_SERVER['SERVER_ADDR'] which returns the current IP of the server the script is running on. 
webKami (et) AKDomains.com
24-May-2005 02:47
PHP Secure Class to prevent XSS Attacks

Although this is not bullet proof but it would give you an idea on how to filter incoming data.

Copyleft : LGPL 
Idea by: phpsec GROUP @ PHP|arch 

Coded By: webKami 

For those who are new to PHP and just heard of XSS attacks, this is the basic rule.

"NEVER EVER TRUST EXTERNAL DATA"

For this purpose I have coded a class that can be used to filter all external data, from POST, GET, COOKIE and even your own arrays.

An example is that if you need only integers from a certain parameter just request for integer
e.g. getVarInt("id")

You can even tell it to give you a default value if param is not set, so that your page would not FAIL in case of a NULL value
e.g. getVarInt("id",1)

You can also fetch data from a param array, like a set of colors
e.g. getVarInt("colors",0,0)
e.g. getVarInt("colors",0,1)

Get these variables in a loop limited by the count of that array's elements
e.g. getVarCount("colors")

The complete code of class and its usage can be found here

http://www.webkami.com/programming/php/php-secure-class-to-avoid-xss

I am posting the usage below.

&lt;?

//for url variables
$req = new requestGet();
echo "Int:".$req-&gt;getVarInt("id")."&lt;br /&gt;";
echo "Alpha:".$req-&gt;getVarAlpha("name",4)."&lt;br /&gt;";

//for form variables
$req = new requestPost();
echo "Int:".$req-&gt;getVarInt("id")."&lt;br /&gt;";
echo "Alpha:".$req-&gt;getVarAlpha("name",4)."&lt;br /&gt;";

//for cookies
$req = new requestCookie();
echo "Int:".$req-&gt;getVarInt("id")."&lt;br /&gt;";
echo "Alpha:".$req-&gt;getVarAlpha("name",4)."&lt;br /&gt;";

//for your own variables, set your values to an item in an array and you can modify the array

$filter["id"]=4;
$filter["name"]="Ali";
$req = new requestFilter($filter);
echo "Int:".$req-&gt;getVarInt("id")."&lt;br /&gt;";
echo "Alpha:".$req-&gt;getVarAlpha("name",4)."&lt;br /&gt;";

?&gt; 
JM
18-May-2005 04:08
The $_SERVER['PHP_AUTH_*'] variables are not available in safe mode.&nbsp; See http://www.php.net/features.http-auth 
www dot php dot net at webdevelopers dot cz
12-May-2005 09:01
Simple function that selects "best" language for the user from the list of available languages:

function chooseLang($availableLangs) {
&nbsp;&nbsp;&nbsp; $pref=array();
&nbsp;&nbsp;&nbsp; foreach(split(',', $_SERVER["HTTP_ACCEPT_LANGUAGE"]) as $lang) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (preg_match('/^([a-z]+).*?(?:;q=([0-9.]+))?/i', $lang.';q=1.0', $split)) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $pref[sprintf("%f%d", $split[2], rand(0,9999))]=strtolower($split[1]);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; krsort($pref);
&nbsp;&nbsp;&nbsp; return array_shift(array_merge(array_intersect($pref, $availableLangs), $availableLangs));
}
&nbsp;
echo 'BESTLANG: '.chooseLang(array('cs', 'sk', 'ru', 'en'));

Daniel "elixon" Sevcik 
exaton at free dot fr
07-May-2005 02:23
With the arrival of the Google Web Accelerator, the problem of keeping track of users through $_SERVER['REMOTE_ADDR'] (for a much shorter while than with cookies) has reared its ugly head anew.

For those confronted with this issue, remember that Google implements the $_SERVER['HTTP_X_FORWARDED_FOR'] header giving the IP address of the connection that it proxies.

Hope this helps... 
inbox at tanasity dot com
13-Apr-2005 09:23
Under Windows 2000, running IIS and PHP 4.3.10, $_SERVER['SCRIPT_NAME'] is not available, however $_SERVER['SCRIPT_FILENAME'] is present and seems to contain the same information. 
javalizard at mac dot com
11-Apr-2005 07:02
My web host server will give my php the user preferred languages out over the order.&nbsp; This means that I had to write a function for ordering the languages based upon their "q" value (rank from 1..0, 1 being the most preferred).&nbsp; If you want an ordered list of user preferred languages use this function:

&lt;?php
function orderedLanguages()
{
&nbsp;&nbsp;&nbsp; $languages = split(",", $_SERVER['HTTP_ACCEPT_LANGUAGE'] );
&nbsp;&nbsp;&nbsp; $lang_q = Array();
&nbsp;&nbsp;&nbsp; foreach( $languages as $aLang ) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lang_array = split(";q=", trim( $aLang ) );
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lang = trim( $lang_array[0] );
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( !isset( $lang_array[1] ) )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $q = 1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $q = trim($lang_array[1]);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lang_q["$lang"] = (float)$q;
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; arsort($lang_q);
&nbsp;&nbsp;&nbsp; //extra code for making the languages key indexed
&nbsp;&nbsp;&nbsp; $i = 0;
&nbsp;&nbsp;&nbsp; $lang_index = Array();
&nbsp;&nbsp;&nbsp; foreach($lang_q as $lang =&gt; $q) {
&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp; $lang_q[$i] = $lang; //add to the same array the index key/language
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lang_index[$i] = $lang; //add to a new array the index key/language
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $i++;
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; //return $lang_index; // uncomment for returning array with keys={0..n-1}, values={most..least preferred}
&nbsp;&nbsp;&nbsp; return $lang_q;
}

?&gt;

While you can't reference the key by number, You can use foreach to pull elements.&nbsp; This will be in order.&nbsp;&nbsp; So getting the key with array_keys should work in the preferred order too.&nbsp; I've added a few extra lines of commented code for reordering the array into one(s) that reference the language by number (if you need it)&nbsp;&nbsp; :D 
skrollster
27-Mar-2005 12:36
$_SERVER["REMOTE_USER"] and $_SERVER['PHP_AUTH_USER'] is the same variable i think.. 
anonymous
04-Mar-2005 06:12
I don't see the $_SERVER["REMOTE_USER"] listed in this document.
This displays the username used to login using .htaccess. 
28-Feb-2005 10:41
Matt Johnson says that one should never urldecode() $_GET data. This is incorrect.

If magic_quotes_gpc is turned off in php.ini, then you *do* need to urldecode() $_GET data.

Having magic_quotes_gpc turned off is considered good practise. 
17-Feb-2005 07:30
grlprgrmmr wrote:

you can use these to reconstructed the current page url.

&lt;?php

echo 'http';
if($_SERVER['HTTPS']=='on'){echo 's';}
echo '://'.$_SERVER['SERVER_PORT'].$_SERVER['SCRIPT_NAME'];
if($_SERVER['QUERY_STRING']&gt;' '){echo '?'.$_SERVER['QUERY_STRING'];}

?&gt;
______________

the $_SERVER['SERVER_PORT'] part should be changed to $_SERVER['HTTP_HOST'] 
Gregory Boshoff
14-Feb-2005 08:19
The Environment variable $ENV is useful for coding portable platform specific application constants. 

// Define a Windows or else Linux root directory path
$_ENV['OS'] == 'Windows_NT' ? $path = 'L:\\www\\' : $path = ' /var/www/';

define('PATH', $path);

echo PATH; 
magotes[at]netcabo.pt
12-Feb-2005 11:09
Sorry if this is old news to some, but it might not be obvious at a first glance:

If you are using $_SERVER['remote_addr'] as a way to keep track of a logged-in user (this can be useful to avoid several types of hacking), remember that it might not be the user's actual IP address!

I was trying to implement a login feature that used this, storing the IP into a DB. It went smoothly while on a LAN, but wrecked havoc when accepting outter connections. 
grlprgrmmr uses gmail
11-Feb-2005 03:05
you can use these to reconstructed the current page url.

[page]

&lt;?php

echo 'http';
if($_SERVER['HTTPS']=='on'){echo 's';}
echo '://'.$_SERVER['SERVER_PORT'].$_SERVER['SCRIPT_NAME'];
if($_SERVER['QUERY_STRING']&gt;' '){echo '?'.$_SERVER['QUERY_STRING'];}

?&gt;

If $_SERVER['HTTPS']=='on' does not work for you,
try $_SERVER['SERVER_PORT']==443 (or whatever secure port is used) 
JSP001
27-Jan-2005 06:15
Hi dotpointer,

I am new to php but I suggest a little modification of your script. Tell me what you think of it :

function getThisFile() {

[...]
&nbsp;&nbsp;&nbsp; /* last resort __FILE__ */
&nbsp;&nbsp;&nbsp; } else {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $strScript = __FILE__;
&nbsp;&nbsp;&nbsp; }
[...]
}

Thanks for this great function, I'll use it for my project !

Regards 
niles AT atheos DOT net
27-Jan-2005 04:51
If your having problems returning $_SERVER variables using apache, be sure you enable:

ExtendedStatus On

in your httpd.conf file.

If it's off, then things like $_SERVER['HTTP_HOST'] won't be present. 
marcus at lastcraft dot com
24-Jan-2005 08:02
The variable $php_errormsg is not populated if you have XDebug running. 
arjini at gmail dot com
19-Jan-2005 08:29
Driven crazy by the lack of consistency with $_SERVER across installations? Check out this chart:

http://www.koivi.com/apache-iis-php-server-array.php 
roy dot rico at gmail dot com
19-Jan-2005 05:48
if you are trying to use $php_errormsg, it acts more like a function than it does a variable.

example 

&nbsp;&nbsp; echo "&lt;h1&gt;";
&nbsp;&nbsp; $php_errormsg;
&nbsp;&nbsp; echo "&lt;/h1&gt;";

will output:

&nbsp;&nbsp; &lt;h1&gt;[the php error]&lt;h1&gt;

however, this command

&nbsp;&nbsp; echo "&lt;h1&gt;" . $php_errormsg . "&lt;/h1&gt;";

should produce the same thing, yet it produces

&nbsp;&nbsp; [the php error]&lt;h1&gt;&lt;/h1&gt;

not sure if this is a "feature" or a "bug" 
dotpointer
10-Jan-2005 05:26
Running Xitami in Windows 2000 and PHP 4.3.7, nor PHP_SELF or SCRIPT_FILENAME is not availiable. Trying SCRIPT_NAME instead. Here is a function that returns the filename of a script without slashes. Good for use in HTML FORM ACTION=""-arguments...

function getThisFile() {

&nbsp;/* try to use PHP_SELF first... */
&nbsp;if (!empty($_SERVER['PHP_SELF'])) {
&nbsp; $strScript = $_SERVER['PHP_SELF'];
&nbsp;/* otherwise, try SCRIPT_NAME */
&nbsp;} else if (!empty($_SERVER['SCRIPT_NAME'])) {
&nbsp; $strScript = @$_SERVER['SCRIPT_NAME'];
&nbsp;/* last resort - quit out and return nothing */
&nbsp;} else {
&nbsp; return null;
&nbsp;}

&nbsp;/* fint last frontslash in filename */
&nbsp;$intLastSlash = strrpos($strScript, "/");

&nbsp;/* check if last backslash is more far away in filename */
&nbsp;if (strrpos($strScript, "\\")&gt;$intLastSlash) {
&nbsp; /* if so, use the backslash position instead */
&nbsp; $intLastSlash = strrpos($strScript, "\\");
&nbsp;}

&nbsp;/* cut out from the last slash and to the end of the filename */
&nbsp;return substr($strScript, $intLastSlash+1, strlen($strScript));
}

Tested on PHP 4.3.7/Win32 and PHP 5.0.3/Linux.
You may add more filepaths to the first if-section 
to get more chances to catch up the filename if you can. 
Matt Johnson
26-Dec-2004 08:50
A reminder: if you are considering using urldecode() on a $_GET variable, DON'T!

Evil PHP:

&lt;?php
# BAD CODE! DO NOT USE!
$term = urldecode($_GET['sterm']);
?&gt;

Good PHP:

&lt;?php
$term = $_GET['sterm'];
?&gt;

The webserver will arrange for $_GET to have been urldecoded once already by the time it reaches you!

Using urldecode() on $_GET can lead to extreme badness, PARTICULARLY when you are assuming "magic quotes" on GET is protecting you against quoting.

Hint: script.php?sterm=%2527 [...]

PHP "receives" this as %27, which your urldecode() will convert to "'" (the singlequote). This may be CATASTROPHIC when injecting into SQL or some PHP functions relying on escaped quotes -- magic quotes rightly cannot detect this and will not protect you!

This "common error" is one of the underlying causes of the Santy.A worm which affects phpBB &lt; 2.0.11. 
mrnopersonality at yahoo dot com
19-Oct-2004 11:13
Nothing about the message-body ...

You can get cookies, session variables, headers, the request-uri , the request method, etc but not the message body. You may want it sometimes when your page is to be requested with the POST method.

Maybe they should have mentioned $HTTP_RAW_POST_DATA or php://stdin 
hfuecks at phppatterns dot com
06-Sep-2004 03:21
Using Apache/mod_ssl, there are further environment variables available to check for an SSL connection (can be more useful than $_SERVER['SERVER_PORT']), documented here: http://www.modssl.org/docs/2.8/ssl_reference.html#ToC25

To test whether the client connected with SSL I can use $_SERVER['HTTPS'] e.g (with redirect to secured, current URL);

&lt;?php
if ( !isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) != 'on' ) {
&nbsp;&nbsp;&nbsp; header ('Location: https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
&nbsp;&nbsp;&nbsp; exit();
}
?&gt; 
boaz at babylon dot com
30-Aug-2004 10:13
You can add $_SERVER["DOCUMENT_ROOT"] to IIS by editing the Environment Variables of your Windows server (was tested on WinXP SP2).

Right click on My Computer &gt;&gt; Properties &gt;&gt; Advanced.
In the System variables click on 'New' and Type in the name field 'DOCUMENT_ROOT' and in the value field&nbsp; the path to your IIS document root folder.

Don't forget to restart your Windows (IIS restart won't load the new settings). 
david at grant dot org dot uk
12-May-2004 08:34
$_SERVER['DOCUMENT_ROOT'] *is* supported by IIS, although only when running PHP as an ISAPI module. 
youdontmeanmuch [at] yahoo.com
06-Apr-2004 12:20
Be carful when using $_SERVER['DOCUMENT_ROOT']; in your applications where you want to distribute them to other people with different server types. It isnt always supported by the webserver (IIS). 
mortoray at ecircle-ag dot com
19-Dec-2003 01:32
The RAW / uninterpreted HTTP POst information can be accessed with:
&nbsp;&nbsp;&nbsp; $GLOBALS['HTTP_RAW_POST_DATA']

This is useful in cases where the post Content-Type is not something PHP understands (such as text/xml). 
josh,endquote,com
04-Dec-2003 07:54
Running PHP 4.3 under IIS 5 on Windows XP, there is no $_SERVER['REQUEST_URI'] variable. This seems to fix it:

if(!isset($_SERVER['REQUEST_URI'])) {
&nbsp;&nbsp;&nbsp; $_SERVER['REQUEST_URI'] = substr($_SERVER['argv'][0], strpos($_SERVER['argv'][0], ';') + 1);
} 

]]></description>
		</item>
		<item>
			<title>PHP 命令行完全解读</title>
			<link>http://www.kingmx.com/article.php?id=15212</link>
			<pubDate>2007-4-19</pubDate>
			<description><![CDATA[PHP，作为命令行工具，它对于 Web 页面来说一直都非常可靠。 
　　当然，只是可以 在命令行中使用 PHP 当然不是这样做的最佳理由。但是，在开始以这种方式用 PHP 进行试验时可能很快就会发现调试现有脚本将变得前所未有地简单。由主要输出和极少逻辑组成的 PHP 程序都将变得令人难以置信地简单。除此之外，还可以使用所有 PHP 知识来完成以前从未想过使用 PHP 完成的任务。事实上，确实没有任何事能阻止您使用 PHP 作为几乎所有给定编程项目的全能王。

　　安装

　　安装十分简单扼要，它甚至可能都不需要特别安装任何内容。开始时先在命令行中尝试一个简单的 PHP 脚本。您可以使用现有 PHP 脚本，也可以尝试使用以下代码。本例是基于 Linux 的，但是类似的原理也适用于其他系统。

　　首先，确认 PHP 可执行文件的位置 —— 对于大多数 Linux 系统，几乎肯定是 /usr/bin/php。如果不确定其位置，请在命令行中键入 which php 并查看响应内容。

　　其次，键入以下代码，确保将 /usr/bin/php 替换为 PHP 可执行文件的实际路径。





　　#!/usr/bin/php&nbsp;-q 
　　Hello&nbsp;world


　　保存文件并确保用可执行权限做了标记。在大多数系统中，您都可以用 chmod +x hello-world 或类似代码完成此操作。然后，执行 PHP 文件(通过运行 ./hello-world 或者，如果有必要，运行 php hello-world)，并查看它是否运行。如果它运行，则安装的 PHP 在默认情况下会包括命令行功能。

　　如果代码未能正确运行，事情可能会变得有点儿麻烦。关于原因有很多种不同的可能性。如果您得到一个与 PHP 相关的错误(除了 “未找到程序” 之类的结果)，则问题是代码中的输入错误。如果未找到 PHP 可执行文件，请确保您使用了正确的路径。如果没有名为 PHP 的可执行文件，则必须获得一个。

　　获得 PHP 可执行文件可能根据所在系统的不同采取不同的步骤，但是获得所需支持不应当太难。您可以从查阅针对特定操作系统或发行版的文档开始。

　　很明显，如果这时系统中未安装 PHP，则先安装 PHP，然后再次尝试执行以上代码。对于许多系统，安装 PHP 是您需要做的全部操作。如果需要执行更多操作，有时只需使用您最喜欢的包管理工具(例如 apt-get 或 yum)获得 PHP CLI 包(名称可能略有不同)就可以解决此问题。

　　如果在 PHP 包管理工具中未能找到命令行，最糟糕的情况是您可以用 --enable-cli 标记重新编译 PHP。事实上，这样做的优点是提供了稍微优化了的系统并且不管怎么说都不是个坏主意。无论采用哪种方式，开始使用它都不应当太难。

　　到现在，您应当已经运行了 HelloWorld 脚本，并且输出就是可能已经猜测到的结果。我不会详细说明该脚本的工作原理，但是使用过 shell 脚本和 PHP 的人应当十分熟悉脚本的大部分内容。由于这第一个脚本现在的运行没有出现任何问题(我们希望如此!)，因此我们将略微偏离真正的命令行接口 (CLI) 应用程序，看一看为什么在命令行中使用 PHP 对于所有 PHP 程序员来说都是最佳选择的好理由：调试。

　　PHP 调试

　　可能只有我有这种体验，但是我经常发现调试 CLI 程序会演变成一场噩梦，尤其是处理嵌入了 HTML 的脚本，例如 Microsoft&reg; Active Server Pages (ASP) 或 PHP。通常很难判断特定错误消息所表达的精确含义，用户输入可能很难再次生成，并且整件事通常会使您头痛的希望拔光头发。

　　不幸的是，虽然足够聪明的程序员可以找到 CLI 能够有所帮助的方法(例如，通过从文件读取输入或通过一个通道的另一个程序)，但是大部分问题都不会由于使用命令行而显著减弱。不过，CLI 确实使一件事变得更加简单：找到错误消息，以便可以在第一位置读取这些错误消息。

　　为了查看使用命令行调试的值，让我们从下面所示的非常非常糟糕的 PHP 文件开始。





#!/usr/bin/php -q
Don&lt;'t&gt;code&lt;?php while drunk(); ?&lt;


［page］

虽然第一眼看到代码时，就发现这个脚本中的一些错误十分明显，但是代码在 Web 浏览器中提供了无用调试信息的极好示例。尤其是，不会发生这种情况：在 Apache 中运行此页面只是得到了根本没有输出的结果。如果错误不明显，那么您怎样找到错误原因?

　　解决这个问题的传统方法是查看错误日志。例如，您可能先运行：





tail&nbsp;-f&nbsp;/var/log/httpd/error_log


　　然后再将页面装入运行 Apache 2 的 Linux 系统，这将得到诸如下面的输出：





[client&nbsp;127.0.0.1]&nbsp;PHP&nbsp;Parse&nbsp;error:&nbsp;parse&nbsp;error,&nbsp;unexpected&nbsp;T_STRING,&nbsp;expecting 
'('&nbsp;in&nbsp;/var/www/html/dont-code-drunk.php&nbsp;on&nbsp;line&nbsp;2


　　不幸的是，您可能同意我的观点，考虑这种不太理想的解决方案。一方面，文件日志位置可能因系统的不同而有所不同。另一方面，您必须浏览不相关事件的日志以查找所需内容，这对于活动的服务器来说很可能是一场噩梦。

　　此时，您可能和我曾经想的一样：一定会有更好的方法。

　　使用 CLI 定位并修正错误

　　通过直接在 CLI 上运行脚本，可以轻松地分离出代码中存在的问题。运行：





php&nbsp;dont-code-drunk.php


　　结果，可能会得到以下输出：





PHP&nbsp;Parse&nbsp;error:&nbsp;parse&nbsp;error,&nbsp;unexpected&nbsp;T_STRING,&nbsp;expecting 
'('&nbsp;in&nbsp;/var/www/html/dont-code-drunk.php&nbsp;on&nbsp;line&nbsp;2 
Content-type:&nbsp;text/html 
X-Powered-By:&nbsp;PHP/4.3.11


　　更棒了!错误消息已与其他数据分离，并且在做出更改后可以轻松地重新查看页面。在这种情况下，很清楚它在行中某个位置需要 '('。while 语句看似适合用在这里，因此添加一组新括号，得到以下源代码。





#!/usr/bin/php -q
Don&lt;'t&gt;code&lt;?php while (drunk()); ?&lt;


　　现在，再次运行代码将得到以下输出：

　　清单 1. 再次运行结果






Content-type: text/html
X-Powered-By: PHP/4.3.11

&lt;'t&gt;codePHP Fatal error:&nbsp; Call to undefined function:
&nbsp;&nbsp;&nbsp; drunk() in /var/www/html/dont-code-drunk.php on line 2


　　脚本仍有很多问题，但是您已经取得了一些进展。您已经相对轻松地提取到了所需的错误消息，使您可以快速修正程序中的问题并继续处理下一个问题。

　　全然使用 PHP 的任何人都可以以这种方式充分利用 CLI PHP 进行调试。但是为什么不进一步伸展您自己并开始用 PHP 真正实现 shell 脚本?向前迈进，并且您将会看到将 PHP 用于简单或者不那么简单的 shell 脚本的一些可能性。

[page]


PHP I/O 通道 
　　为第一个 PHP 脚本制定一个简单的初始目标：创建一个能读入文件并打乱该文件中各行的脚本。如果要打乱 m3u 文件或类似内容，则使用此功能可能很便利。这样做意味着您必须能够从文件或标准输入读取数据并将数据写回终端。

　　这将出现 PHP 中的第一大挑战。PHP 最初不是设计用于与用户直接的键盘输入或文本输出结合使用。了解这一设计是至关重要的，因为如果需要在命令行中执行任何操作，都必须能够与用户来回通信。在诸如 C 之类的传统编程语言中，您将使用 STDIN、STDOUT 和 STDERR 完成此操作。您可以将 PHP 中的相同通道分别用于输入、标准输出和输出到错误通道。

　　STDOUT：echo、print、STDOUT 和 php://stdout

　　即使 PHP 设计用于输出到浏览器而不是输出到 CLI，从 PHP 创建输出也是非常简单的，它几乎不需要花太多时间思考。记住，PHP 标记外的任何内容都将被直接输出到 CLI，这就是上面的 HelloWorld 程序如此简单的原因。这也是为什么先输出上面的 Don&lt;'t&gt;code 后再输出错误消息的原因。您是否用 HTML 标记圈起文字都没有关系;因为不管怎样都会显示这些文字。事实上，您通常需要避免使用 HTML 标记，因为它们都将直接打印给用户。

　　您还可以使用基本函数进行输出。例如，echo 和 print 命令打印到标准输出。





#!/usr/bin/php -q
Output #1.
&lt;?php echo "Output #2.";
print "Output #3."?&gt;


　　这将得到：





Output&nbsp;#1. 
Output&nbsp;#2.Output&nbsp;#3.


　　注：PHP 标记外的新行已被输出，但是 echo 命令或 print 命令中没有暗含的新行。事实上，命令提示符重新出现在 Output #2.Output #3. 所在的行中。PHP 拥有的任何其他打印函数将会像此函数一样运行正常，任何写回文件的函数也是一样的。





#!/usr/bin/php -q
&lt;?php
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $STDOUT = fopen("php://stdout", "w");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fwrite($STDOUT, "Output #1.");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fclose($STDOUT);
?&gt;


　　以上代码将把 php://stdout 作为输出通道显式打开，并且 php://output 通常以与 php://stdout 相同的方法运行。最新版本的 PHP 可以使用 STDOUT 作为常量而不是定义上面使用的变量 $STDOUT。

　　STDERR：STDERR 和 php://stderr

　　STDERR 与 STDOUT 十分接近。用于写入此通道的所有技术将镜像 STDOUT 的那些技术，惟一的差别是您将打开 php://stderr 而不是 php://stdout 或 php://error。

　　STDIN：STDIN 和 php://stdin

　　STDIN 是从 Web 编程而来的最有趣更改，因为它向您展示了真正的用户输入而不是使用表单或其他基于浏览器的方法。尝试以下命令：





#!/usr/bin/php -q
&lt;?php
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $file = file_get_contents("php://stdin", "r");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo $file;
?&gt;


　　这段代码的工作原理应当很像 cat，回转提供给它的所有输入。但是，这时它还不能接受参数。


[page]

第一个 PHP shell 脚本

　　很好 —— 从这里开始事情会变得非常有趣。运用到目前为止学到的简单知识，您可以创建简单而有用的 shell 脚本。在文本编辑器中键入以下代码。

　　清单 2. randomize-lines





#!/usr/bin/php -q
&lt;?php
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lines = split("\n", file_get_contents("php://stdin", "r"));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shuffle($lines);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach ($lines as $line) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ($line !== "") {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "$line\n";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
?&gt;


　　现在，只需一些快速检查即可运行这个脚本：


　　确保 hashbang(第一行，以 #! 开头)被设为先前描述的 PHP 可执行文件的位置 
　　保存文件 
　　使用 chmod 添加可执行权限 
　　运行程序

　　注：randomize-lines 将完全执行所期望的操作：它打乱键入的输入内容行并将它们以不同的顺序返回回来。这项功能可以颇具价值地填补 shell 脚本库中的空白。

　　作为此脚本的应用程序示例，您可以使用它为音乐或视频播放器动态生成随机播放列表。例如，要打乱 XMMS 播放列表，请尝试：





./randomize-lines &lt; .xmms/xmms.m3u &gt; temp
mv temp .xmms/xmms.m3u


　　现在，再升一级。

　　命令行参数

　　实际命令行程序使用参数。同样，就像 C 语言和其他类似语言一样，您可以为此目的而使用 argv 和 argc。特别是，argv 是程序的参数数组，第一个参数是程序本身。使用这个函数，构建根据给定参数从文件或用户输入读取数据的程序就不难了。例如，请查看以下代码。

　　清单 3. randomize-lines-w-args





#!/usr/bin/php -q
&lt;?php
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; array_shift($argv);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (count($argv) == 0) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $argv[0] = "php://stdin";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach ($argv as $file) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lines = split("\n", file_get_contents($file, "r"));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shuffle($lines);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach ($lines as $line) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ($line !== "") {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "$line\n";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
?&gt;　　?&gt;


　　现在您拥有这样一个程序：完全运行的 CLI PHP 程序，它可以接受用户输入，也可以接受文件列表并随机排列每个文件的相关内容。

　　结束语

　　最佳工具通常都不是期望使用的那一个工具。在命令行接口中使用PHP，会发现它已经成为 shell 脚本工具新宠。
]]></description>
		</item>
		<item>
			<title>php+ajax文件上传进度条</title>
			<link>http://www.kingmx.com/article.php?id=15211</link>
			<pubDate>2007-4-19</pubDate>
			<description><![CDATA[代码分为以下部分: 
&nbsp;&nbsp; 
&nbsp;&nbsp;demo.php - 上传过程处理 
&nbsp;&nbsp; 
&nbsp;&nbsp;PLAIN TEXTPHP: 
&nbsp;&nbsp; 
&nbsp;&nbsp;&lt;?php 
&nbsp;&nbsp; 
&nbsp;&nbsp;include 'UploadProgressMeter.class.php'; 
&nbsp;&nbsp; 
&nbsp;&nbsp;$fileWidget = new UploadProgressMeter(); 
&nbsp;&nbsp; 
&nbsp;&nbsp;if ($fileWidget-&gt;uploadComplete()) { 
&nbsp;&nbsp; // 上传完毕的时候,从iframe发送一个js到主窗口表示一切ok 
&nbsp;&nbsp; echo $fileWidget-&gt;finalStatus(); 
&nbsp;&nbsp; 
&nbsp;&nbsp; // 处理上传后的文件... 
&nbsp;&nbsp; 
&nbsp;&nbsp; exit; 
&nbsp;&nbsp;} 
&nbsp;&nbsp;?&gt; 
&nbsp;&nbsp; 
&nbsp;&nbsp;demoserver.php - Ajax的服务端js,使用Pear:HTML_AJAX,直接调用UploadProgressMeterStatus类 
&nbsp;&nbsp; 
&nbsp;&nbsp;PLAIN TEXTHTML: 
&nbsp;&nbsp; 
&nbsp;&nbsp;&lt;script src="http://www.ooso.net/demoserver.php?client=main,request,httpclient,dispatcher,json,util" type="text/javascript"&gt;&lt;/script&gt; 
&nbsp;&nbsp;&lt;script src="http://www.ooso.net/demoserver.php?stub=UploadProgressMeterStatus" type="text/javascript"&gt;&lt;/script&gt; 
&nbsp;&nbsp;&lt;?php echo $fileWidget-&gt;renderIncludeJs(); ?&gt; 
&nbsp;&nbsp; 
&nbsp;&nbsp;进度条的样式表 
&nbsp;&nbsp; 
&nbsp;&nbsp;PLAIN TEXTCSS: 
&nbsp;&nbsp; 
&nbsp;&nbsp;.progressBar { 
&nbsp;&nbsp; position: relative; 
&nbsp;&nbsp; padding: 2px; 
&nbsp;&nbsp; width: 300px; 
&nbsp;&nbsp; height: 40px; 
&nbsp;&nbsp; font-size: 14px; 
&nbsp;&nbsp;} 
&nbsp;&nbsp;.progressBar .background { 
&nbsp;&nbsp; border: solid 1px black; 
&nbsp;&nbsp; width: 270px; 
&nbsp;&nbsp; height: 20px; 
&nbsp;&nbsp;} 
&nbsp;&nbsp;.progressBar .bar { 
&nbsp;&nbsp; position: relative; 
&nbsp;&nbsp; background-color: blue; 
&nbsp;&nbsp; width: 0px; 
&nbsp;&nbsp; height: 20px; 
&nbsp;&nbsp;} 
&nbsp;&nbsp; 
&nbsp;&nbsp;表单部分 
&nbsp;&nbsp; 
&nbsp;&nbsp;PLAIN TEXTHTML: 
&nbsp;&nbsp; 
&nbsp;&nbsp;&lt;form action="demo.php" method="post" enctype="multipart/form-data"&gt;renderFormExtra(); ?&gt;&gt; 
&nbsp;&nbsp;&lt;?php echo $fileWidget-&gt;renderHidden(); ?&gt;&lt;/form&gt;&lt;form action="demo.php" method="post" enctype="multipart/form-data"&gt;&lt;label&gt;Select File: &lt;/label&gt; 
&nbsp;&nbsp;&lt;div&gt;&lt;?php echo $fileWidget-&gt;render(); ?&gt; 
&nbsp;&nbsp;&lt;?php echo $fileWidget-&gt;renderProgressBar(); ?&gt;&lt;/div&gt; 
&nbsp;&nbsp;&lt;/form&gt; 
&nbsp;&nbsp; 
&nbsp;&nbsp; 
&nbsp;&nbsp;demo下载 - 密码是www.ooso.net 
&nbsp;&nbsp;作者的svn浏览 
&nbsp;&nbsp; 
&nbsp;&nbsp;其它类似项目: 
&nbsp;&nbsp;http://pdoru.from.ro/ - 要以patch的形式和php一起编译 
&nbsp;&nbsp;http://www.ugia.cn/?p=54 - 以socket上传文件并显示进度条 
]]></description>
		</item>
		<item>
			<title>php调用存储过程返回结果集，解决can\&apos;t return a result set in</title>
			<link>http://www.kingmx.com/article.php?id=15210</link>
			<pubDate>2007-4-19</pubDate>
			<description><![CDATA[
需要php调用存储过程，返回一个结果集，发现很困难，找了半天，终于在老外的论坛上找到解决方案，这里本地化一下。 
关键就是两点

1）define('CLIENT_MULTI_RESULTS', 131072);

2）$link = mysql_connect("127.0.0.1", "root", "",1,CLIENT_MULTI_RESULTS) or die("Could not connect: ".mysql_error());

下面就可以正常使用了，以下是例子程序。

&nbsp;

&lt;?php
&nbsp;&nbsp;&nbsp; define('CLIENT_MULTI_RESULTS', 131072);

&nbsp;&nbsp;&nbsp; $link = mysql_connect("127.0.0.1", "root", "",1,CLIENT_MULTI_RESULTS) or die("Could not connect: ".mysql_error());
&nbsp;&nbsp;&nbsp; mysql_select_db("vs") or die("Could not select database");
?&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;?php
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $result = mysql_query("call get_news_from_class_id(2)") or die("Query failed:" .mysql_error());
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while($row = mysql_fetch_array($result, MYSQL_ASSOC))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $line = '&lt;tr&gt;&lt;td&gt;&lt;a target = _blank href=\''.$row["url"].'\'&gt;'.$row["title"].'('.$row["page_time"].')'.'&lt;/a&gt;&lt;/td&gt;&lt;/t
r&gt;';
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo $line;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("\n");

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mysql_free_result($result);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ?&gt; 

&nbsp;

&lt;?php
&nbsp;&nbsp;&nbsp; mysql_close($link);
?&gt;

]]></description>
		</item>
		<item>
			<title>用PHP自动把纯文本转换成Web页面</title>
			<link>http://www.kingmx.com/article.php?id=15209</link>
			<pubDate>2007-4-19</pubDate>
			<description><![CDATA[
最近，我的一个老朋友向我打电话求助。他从事记者的职业有多年了，最近获得了重新出版他的很多早期专栏的权利。他希望把他的作品贴在Web上;但是他的专栏都是以纯文本文件的形式保存的，而且他既没有时间也不想去为了把它们转换成为Web页面而学习HTML的知识。由于我是他电话本里唯一一个精通计算机的人，所以他打电话给我看我是否能够帮帮他。 
　　“让我来处理吧，”我说：“一个小时以后再给我打电话。”当然了，当他几个小时以后打电话过来，我已经为他准备好了解决的方法。这需要用到一点点PHP，而我收获了他没完没了的感谢和一箱红酒。

　　那么我在这一个小时里做了些什么呢?这就是本篇文章的内容。我将告诉你如何使用PHP来快速将纯ASCII文本完美地转换成为可读的HTML标记。

　　首先让我们来看一个我朋友希望转换的纯文本文件的例子：

　　Green for Mars!

　　John R. Doe

　　The idea of little green men from Mars, long a staple of science fiction, may soon turn out to be less fantasy and more fact.

　　Recent samples sent by the latest Mars exploration team indicate a high presence of chlorophyll in the atmosphere. Chlorophyll, you will recall, is what makes plants green. It's quite likely, therefore, that organisms on Mars will have, through continued exposure to the green stuff, developed a greenish tinge on their outer exoskeleton.

　　An interview with Dr. Rushel Bunter, the head of ASDA's Mars Colonization Project blah blah...

　　What does this mean for you? Well, it means blah blahblah...

　　Track follow-ups to this story online at http://www.mars-connect.dom/. To see pictures of the latest samples, log on to http://www.asdamcp.dom/galleries/220/

　　相当标准的文本：它有一个标题、一个署名和很多段的文字。把这篇文档转换成为HTML真正需要做的是使用HTML的分行和分段标记把原文的布局保留在Web页面上。特殊的标点符号需要被转换成为对应的HTML符号，超链接需要变得可以点击。

　　下面的PHP代码(列表A)就会完成上面所有的任务：

　　列表A

　　让我们来看看它是如何工作的：

以下是引用片段：
&lt;?php 
// set source file name and path 
$source = "toi200686.txt"; 

// read raw text as array 
$raw = file($source) or die("Cannot read file"); 

// retrieve first and second lines (title and author) 
$slug = array_shift($raw); 
$byline = array_shift($raw); 

// join remaining data into string 
$data = join('', $raw); 

// replace special characters with HTML entities 
// replace line breaks with &lt;br /&gt; 
$html = nl2br(htmlspecialchars($data)); 

// replace multiple spaces with single spaces 
$html = preg_replace('/ss+/', ' ', $html); 

// replace URLs with &lt;a href...&gt; elements 
$html = preg_replace('/s(w+://)(S+)/', ' &lt;a href="" target="_blank"&gt;&lt;/a&gt;', $html); 

// start building output page 
// add page header 
$output =&lt;&lt;&lt; HEADER 
&lt;html&gt; 
&lt;head&gt; 
&lt;style&gt; 
.slug {font-size: 15pt; font-weight: bold} 
.byline { font-style: italic } 
&lt;/style&gt; 
&lt;/head&gt; 
&lt;body&gt; 
HEADER; 

// add page content 
$output .= "&lt;div class='slug'&gt;$slug&lt;/div&gt;"; 
$output .= "&lt;div class='byline'&gt;By $byline&lt;/div&gt;&lt;p /&gt;"; 
$output .= "&lt;div&gt;$html&lt;/div&gt;"; 

// add page footer 
$output .=&lt;&lt;&lt; FOOTER 
&lt;/body&gt; 
&lt;/html&gt; 
FOOTER; 

// display in browser 
echo $output; 

// AND/OR&nbsp; 

// write output to a new .html file 
file_put_contents(basename($source, substr($source, strpos($source, '.'))) . ".html", $output) or die("Cannot write file"); 
?&gt; 

　　第一步是把纯ASCII文件读取到一个PHP数组里。这通过file()函数很容易就可以完成，这个函数会把文件的每一行都转换成为一个用数字索引的数组中的元素。

　　然后，标题和作者行(我假设这两个都是文件的前两行)都通过array_shift()函数从数组里提取出来，放到单独的变量里。数组剩下的成员然后被连接成一个字符串。这个字符串现在就包括了整篇文章的正文。

　　文章正文里像“'”、“&lt;”和“&gt;”这样的特殊符号通过htmlspecialchars()函数被转换成相应的HTML符号。为了保留文章的原始格式，分行和分段通过nl2br()函数被转换成HTML的
元素。文章中间多个空格通过简单的字符串替换被压缩成为一个空格。

　　文章正文里的URL用正则表达式来检测，两边是元素。当页面在Web浏览器里显示的时候，它会把URL转换成为可点击的超链接。

　　然后用标准的HTML规则创建输出的HTML页面。文章的标题、作者和正文都用CSS样式规则格式化。尽管这段脚本没有这样做，但是你可以在这个地方自定义最终页面的外观，你可以向模板添加图形元素、颜色或者其他眩目的内容。

　　一旦HTML页面构建完成，它就可以被送到浏览器或者用file_put_contents()保存为静态文件。要注意的是，在保存的时候，原来的文件名会被分解，一个新的文件名(叫做filename.html)会为新创建的Web页面创建。你然后就可以把这个Web页面发布到Web服务器上、保存到光盘上或者对它进行进一步编辑。

　　注意：在使用这个脚本创建和保存HTML文件到磁盘的时候，你要确保这个脚本对文件保存的目录有写权限。

　　正如你看到的，假如你有标准格式的ASCII纯文本数据文件，你可以相当迅速用PHP把它转换成为可使用的Web页面。如果你已经有了一个Web网站，并计划把新的Web页面加入进来，那么调试页面生成器所使用的模板，使之适应原有Web网站的外观是相当容易的。你自己试试看!

]]></description>
		</item>
		<item>
			<title>教你用PHP写MySQL数据库用户认证系统</title>
			<link>http://www.kingmx.com/article.php?id=15208</link>
			<pubDate>2007-4-19</pubDate>
			<description><![CDATA[

这两天受朋友的托付，要我帮他写一个使用MySQL数据库的用户认证系统。我当然不好推脱的，只得耗费了一晚上的休息时间，写了个很简单的PHP程序。 

用户认证的原理很简单：首先需要用户在页面上填入用户名和密码，当然没注册的用户需要先注册。然后调用数据库搜索是否有相应的用户。如果有就确认，没有则提醒用户先注册。使用PHP来完成这一切很简单，但需要注意的是如果想在以后的页面中都能确认用户身份，使用PHP3我只能想出使用cookie的方法。要想使用session,就只能等待PHP4正式版的发布了！ 

第一步是做一个登录的页面，这儿就不多讲了。我只做了个极简单的，大家可以做得漂亮点。 

第二步开始登录后的确认程序的设计。 






login.php: 
mysql_connect("localhost","user","password") 
/*连接数据库，用户名和密码自行修改*/ 
or die("无法连接数据库，请重试"); 

mysql_select_db("userinfo") 
or die("无法选择数据库，请重试"); 
$today=date("Y-m-d H:i:s"); 

$query=" 
select id 
from usertbl 
where name=$name and password=$password 
/*从数据库中搜索和登录用户相应的资料*/ 
"; 
$result=mysql_query($query); 
$numrows=mysql_num_rows($result); 


if($numrows==0){ 
/*验证是否能找出相同资料的用户，不能则未注册*/ 
echo 非法用户
; 
echo 请注册先
; 
echo 重试
; 
} 

else{ 
$row=mysql_fetch_array($result); 
$id=$row[0]; 
$query=" 
update usertbl 
set lastlogin=$today 
where id=$id"; 
$result=mysql_query($query); 
SetCookie("usercookie", "欢迎你,$name");
 /*这里使用了cookie，以方便之后的页面认证。
但我未开发完这一块。希望有兴趣的朋友指正*/ 
echo 登录成功
; 
echo 请进！
; 
} 
?&gt;

第三步当然是做好注册的页面，也不多讲了。 

第四步是注册后的身份确认和输入数据库。 






register.php: 
mysql_connect("localhost","user","password") /*请修改用户名和密码*/ 
or die("无法连接数据库，请重试"); 

mysql_select_db("userinfo") 
or die("无法选择数据库，请重试"); 
$query="select id from usertbl where name=$name\";
 /*从数据库中搜索相同名字的用户资料*/ 
$result=mysql_query($query); 
$numrows=mysql_num_rows($result); 
if($numrows!=0) /*找到了当然就是有人先注册了相同的名字*/ 
{echo 已有人注册此名，请重新选择名字!;} 
else 
{$query="insert into usertbl values(0,$name,$password,\)";
 /*找不到相同的就输入新的用户资料*/ 
mysql_query($query); 
echo 注册成功; 
echo 请登录!;} 
?&gt;

下一步是cookie的使用，我原打算使用cookie来使每一页都能识别用户身份，但由于别的页面还没做好，不知道需要用到哪些资料。于是就只有一个很简单的使用，这里用到了php的引用: 






if(!$usercookie) 
{header("非法用户"); 
} 
?&gt; 

welcome.php: 

require("cookie.php"); /*调用cookie.php*/ 
?&gt; 

echo $usercookie; 
?&gt;

到这儿便完成了一个很简单的用户认证系统，当然如果你要使用它还得建好数据库。下面是我的数据库表的结构,库的名字是userinfo。 






create table usertbl 
( 
ID int auto_increment primary key, 
Name varchar(30), 
Password varchar(20), 
Lastlogin varchar(20) 
);

]]></description>
		</item>
		<item>
			<title>关于PHP无法连接MSSQL数据库的问题</title>
			<link>http://www.kingmx.com/article.php?id=15207</link>
			<pubDate>2007-4-19</pubDate>
			<description><![CDATA[
今天配置了新服务器，配置是IIS+php，结果运行时发现php连接远程mssql数据库出错，出错代码如下：
Warning: mssql_connect(): Unable to connect to server:
想想以前都是没问题的，怎么回事呢？后来去网上搜索，发现一篇文章，才发现原来服务器是需要安装mssql才能用php连接mssql的，本来新服务器上我是不需要用到mssql的，但是现在没办法了，只能把它装上了，安装了mssql之后就没问题了。
我在想，如果是在linux上面的apache+php会怎样呢，不可能需要安装mssql吧，呵呵，晕了。
下面是找到的一篇文章。

php配置：
在php.ini文件里设置如下，找到&nbsp; 
；extension=php_mssql.dll&nbsp; 把前面的分号去掉&nbsp; 
找到extension_dir&nbsp; =&nbsp; d:\extension\&nbsp; 
你的php.ini里面可能不是d:\extension\&nbsp; 
改成在php安装目录下面的extensions目录下面的php_mssql.dll，所在的路径，如果你没有把它移动到其他地方（假设你的php安装路径是d:\php）&nbsp; 
就改成extension_dir=d:\php\extensions\&nbsp; 
然后重新启动web服务器

这一点很容易做到，但是做完这样的设置后还是连不上，错误的信息如下：

MS SQL Server 数据库连接错误!请检查数据库主机变量设置是否正确!!! 

而主机的变量设置我是一遍一遍的检查，那些设置是一点问题都没有的，翻遍网页，找到了下面的这点蛛丝马迹：

php.com资料：

I am trying to connect to SQL Server 2000 from PHP 
I bumped to following warning: 
Warning: mssql_connect(): Unable to connect to server: SERVER\Portal 
....... on line 5 

on line 5 there is: 
$db_connect = mssql_connect('SERVER\Portal', 'sa', 'my_passwd'); 

I did the following 
1.enabled php_mssql.dll extension in PHP.ini 
2.every dll is in proper place(System32 or PHP folder),including ntwdblib.dll 

I search lots of profile throught web ,but no one give me proper answer to resolve it. 

after a few hour ,I found the problem was caused by 
ntwdblib.dll ,which version is 7.00.839 ,when I replaced old ntwdblib.dll with the new 

ntwdblib.dll ,which version is 8.00.194 ,all problem are solved. 

We had some, read A LOT, of problems with MSSQL under Windows 2003. 
We had 2 the same windows, php, php-ini, everything machines but only one could connect. 

Unable to connect was the error message. 

Finnaly we checked the version of ntwdblib.dll and the one distributed with PHP was 7.00.... 

and the version of the one on the SQL Server install was 8.00.... so we copied this one in 

the php and apache dir and it worked. 

问题就这样被找到了，惹祸的是它 ntwdblib.dll

ntwdblib.dll的主要作用是提供sql server连接服务。

我用的php版本是4.3.9，在安装它的服器的 windows/system32/ 下我查到ntwdblib.dll文件的版本是2000.2.8.0 ，这个版本支持的是sql server 7.0， 因为安装PHP时会把dlls下面的所有文件覆盖到系统

目录下，所以当我用它去连接 sql server 2000 的时候当然会是无法连接了。

后来我在一台正常安装sql server 2000 的服务器上查到 ntwdblib.dll的版本是 2000.80.2039.0，我把这个文件拷过去，覆盖掉以前的版本，重启服务器后，一切正常。

&nbsp;

补充：如果数据库名的开头是数字时也会提示无法打开，这时要做的很简单，把数据库的名字用中括号 [ ] 

括起来就搞定了，如 123bbs 改写成 [123bbs]就没有问题了，另外如果你的数据库名字与sql server中的保留字冲突的话也会出现这种情况，用中括号的方法一样可以解决。

最终，PHP无法正确连接sql server 2000的问题终于解决了，虽然耗费大半天的时间，但收获还是很大的，现在把它贴出来，也让遇到同样问题的兄弟们少走一些弯路。
]]></description>
		</item>
		<item>
			<title>PHP程序员的优化调试技术和技巧</title>
			<link>http://www.kingmx.com/article.php?id=15206</link>
			<pubDate>2007-4-19</pubDate>
			<description><![CDATA[

本文介绍调试PHP应用程序的各种方法，包括在Apache and PHP中打开错误报告，以及通过在一个简单的PHP脚本中放置策略性的print语句，找到更困难的bug的源头。还会介绍用于Eclipse的PHPEclipse插件，这是一个灵活的开发环境，具有实时语法解析能力，还会介绍PHPEclipse的DBG调试器扩展。 

&nbsp;

简介

有许多 PHP 调试技术可以在编码的时候节约大量时间。一个有效却很基本的调试技术就是打开错误报告。另一个略微高级一点的技术包括使用 print 语句，通过显示在屏幕上实际出现的内容，有助于精确地找出更难发现的 bug。PHPEclipse 是一个 Eclipse 插件，能够强调常见的语法错误，可以与调试器结合起来用于设置断点。

设置

要学习本文描述的概念，需要 PHP、Web 服务器和 Eclipse。调试器扩展支持的 PHP 版本是 V5.0.3。 

我们需要一个 Web 服务器来解析用 PHP 创建的页面并把它们显示到浏览器。本文中使用的是 Apache2。但是，任何 Web 服务器都可以满足要求。 

要利用本文中介绍的一些调试技术，需要安装 Eclipse V3.1.1 和插件 PHPEclipse V1.1.8。由于 Eclipse 要求 Java? 技术，所以还要下载它。 

还需要 PHP 的调试器扩展模块。安装它略有些麻烦。请仔细跟随安装调试器扩展的操作说明。现在，先在 php.ini 文件中注释掉那些要求装入和配置 PHP 扩展的行。在需要使用调试器的时候，再取消注释。

请参阅 参考资料 获得下载信息。现在介绍出错消息。

出错消息

出错消息是作为开发人员的第一道防线。谁都不想在一台没有配置成显示出错消息的服务器上用 PHP 开发代码。但是，请记住，当代码调试完成，准备运行的时候，应当确保关闭了错误报告，因为不希望站点的访问者看到出错消息，因为这会给他们提供足够的信息来利用站点的弱点并黑掉站点。

也可以用出错消息为自己服务，因为它们会显示抛出或生成错误的正确代码行。这样，调试就变成在浏览器上查看生成的错误所显示的行号，并在代码中检查这一行。稍后，将会看到 PHPEclipse 插件通过即时地给语法错误加下划线并在保存文件时用红色 “x” 标注语法错误，可在开发和调试过程中提供极大的帮助。

先来看如何在 php.ini 文件中开启错误报告并设置错误报告的级别。然后将学习如何在 Apache 的配置文件中覆盖这些设置。

PHP 的错误报告

php.ini 文件中有许多配置设置。您应当已经设置好自己的 php.ini 文件并把它放在合适的目录中，就像在 Linux 上安装 PHP 和 Apache 2 的文档说明中所示的那样（请参阅 参考资料）。在调试 PHP 应用程序时，应当知道两个配置变量。下面是这两个变量及其默认值：





display_errors = Off 
error_reporting = E_ALL


通过在 php.ini 文件中搜索它们，可以发现这两个变量当前的默认值。display_errors 变量的目的很明显 —— 它告诉 PHP 是否显示错误。默认值是 Off。但是，要让开发过程更加轻松，请把这个值设为 On：





display_errors = On


error_reporting 变量的默认值是 E_ALL。这个设置会显示从不良编码实践到无害提示到出错的所有信息。E_ALL 对于开发过程来说有点太细，因为它在屏幕上为一些小事（例如变量未初始化）也显示提示，会搞糟浏览器的输出。我只想看到错误和不良编码实践，但是不想看到无害的提示。所以，请用以下值代替 error_reporting 的默认值：





error_reporting = E_ALL &amp; ~E_NOTICE

重新启动 Apache，就全部设置好了。接下来，将学习如何在 Apache 上做同样的事。
[page]
服务器上的错误报告
依赖于 Apache 正在做的工作，在 PHP 中打开错误报告可能没法工作，因为在计算机上可能有多个 PHP 版本。有时很难区分 Apache 正在使用哪个 PHP 版本，因为 Apache 只能查看一个 php.ini 文件。不知道 Apache 正在使用哪个 php.ini 文件配置自己是一个安全问题。但是，有一种方法可以在 Apache 中配置 PHP 变量，从而保证设置了正确的出错级别。
而且，最好知道如何在服务器端设置这些配置变量，以否决或抢占 php.ini 文件，从而提供更高级别的安全性。
在配置 Apache 时，应该已经接触过 &lt;apache2-install-dir&gt;/conf/httpd.conf 中 http.conf 文件中的基本配置。
要做在 php.ini 文件中已经做过的事，请把下列各行添加到 httpd.conf，覆盖任何 php.ini 文件：





php_flag  display_errors        on 
php_value error_reporting       2039

这会覆盖在 php.ini 文件中为 display_errors 已经设置的标志，以及 error_reporting 的值。值 2039 代表 E_ALL &amp; ~E_NOTICE。如果愿意采用 E_ALL，请把值设为 2047。同样，还是要重启 Apache。
接下来，要在服务器上测试错误报告。

测试错误报告
如果启动了错误报告，会节约许多时间。PHP 中的错误会指向代码中的错误。请创建一个简单的 PHP 文件 test.php，并像清单 1 所示一样定义它。
清单1：一个生成错误的简单PHP





&lt;?php 
print("The next line generates an error.&lt;br&gt;"); 
printaline("PLEASE?"); 
print("This will not be displayed due to the above error."); 
?&gt; 


第一个 print() 语句会向 Web 浏览器显示它的内容。但是第二个语句会生成错误并在 Web 页面上显示。这造成最后一个 print() 语句不起作用，如图 1 所示。
图1：生成错误

498)this.style.width=498;}">
现在开启了错误报告！接下来，用 print 语句帮助调试应用程序。
介绍 print 语句
因为应用程序中的功能性 bug 不会产生错误，所以在所有调试策略中，关于如何正确地放置和使用 print 或 die 语句来调试 PHP 应用程序的知识是一种很好的资产。可以用 print 语句在代码中缩小对问题语句的定位，这些语句在语法上没有错误，也不是 bug，但是从代码的功能上看是 bug。这些是最难发现和调试的 bug，因为它们不会抛出错误。惟一知道的就是在浏览器上显示的内容不是想要的内容，或者想要保存在数据库中的内容根本没有保存。
假设正在处理通过 GET 请求发送过来的表单数据，想向浏览器显示信息，但是出于某种原因，数据没有正确地提交，或者不能正确地从 GET 请求中读出。要调试这类问题，重要的是用 print() 或 die() 语句知道变量的值是什么。
die() 语句会中止程序执行，并在 Web 浏览器上显示文本。如果不想注释掉代码，而且只想显示到出错之前的信息和出错信息，不想显示后面的信息，那么 die() 语句特别有用。
让我们在 PHP 中用 print 语句来测试这个概念
使用 print 语句进行调试
在我作程序员的那些时候，当我在 Linux? 上开发应用程序时，没有方便的 GUI 可以告诉我 bug 在哪，我迅速地发现我在程序中放的 print 语句越多，我在应用程序中把 bug 的范围缩小到一行的机会越大。请创建另一个 PHP 文件 test2.php，并像清单 2 所示的那样定义它。
[page]
清单2：显示通过 GET 提交的所有变量





&lt;?php 
 $j = ""; 
 print("Lets retrieve all the variables submitted to this "); 
 print("script via a GET request:&lt;br&gt;"); 
 foreach($_GET as $key =&gt; $i){ 
     print("$key=$j&lt;br&gt;"); 
 } 
 if($_GET['Submit'] == "Send GET Request") 
     $j = "done!&lt;br&gt;"; 
?&gt; 
&lt;form method="GET"&gt; 
     Name: &lt;input name="name"&gt;&lt;br&gt; 
     Email: &lt;input name="email" size="25"&gt;&lt;br&gt; 
     &lt;input name="Submit" type="submit" value="Send GET Request"&gt; 
&lt;/form&gt;


您可能会非常容易地发现清单 2 中的 bug！您很棒！但请注意这是一个非常简单的脚本，只是作为使用 print 语句进行调试而展示的一个例子而已。这个脚本只是提取 GET 请求中的所有变量，如果有，就把它们显示在浏览器上。还提供了一个表单，用 GET 请求向服务器发送变量以进行测试。请看输出，如图 2 所示。
图2：test2.php 的输出

498)this.style.width=498;}">

现在单击 Send GET Request 按钮，请注意只有 $_GET 请求的键显示在浏览器上，而正确的值都没显示。可以在循环中放一个 print 语句，检验在 foreach 循环中每个元素中是否确实存在数据。请参阅清单 3。 


清单3：用 print 语句验证代码的功能





... 
 foreach($_GET as $key =&gt; $i){ 
     print("Correct data? " . $_GET[$key] . "&lt;br&gt;"); 
     print("$key=$j&lt;br&gt;"); 
 } 
... 


放进去的 print 语句是粗体。注意，现在已经知道在 Web 浏览器上显示的 $key 值是正确的，但是由于某些原因，值没有正确地显示。请看新的输出，如图 3 所示。
图3：修改后的 test2.php 的输出

498)this.style.width=498;}">
现在已经知道应用程序正确地从 GET 请求接收到了变量，那么肯定是在代码中有 bug。查看之后注意到，用来显示值的变量 $j 是错误的。在 foreach 语句中指定的是 $i，所以它肯定会有正确的值，但是无意之中输入了 $j。所以通过把 $j 替换成 $i，迅速地修正了错误，重新载入页面之后，就看到了正确的输出，如图 4 所示。
图4：修正后的 test2.php 的输出

498)this.style.width=498;}">
现在可以删除或注释掉刚才添加的 print 语句了，因为已经发现了代码中的 bug。注意，这只是在调试应用程序时可能遇到的许多错误中的一个很小的子集。对于使用数据库时可能遇到的问题，一个好的解决方案是输出 SQL 语句，以确保执行的 SQL 就是想要执行的。
现在要来看看如何使用 Eclipse IDE 和 PHPEclipse 插件及调试器扩展进一步在调试历程中提供帮助。

[page]

使用 PHPEclipse
您可能用过 Eclipse，但是可能不熟悉它。请参阅 参考资料 获得 Eclipse 平台的介绍。
用于 Eclipse 的 PHPEclipse 插件是用来开发 PHP 应用程序的一个流行工具。请启动 Eclipse 并把工作区目录指定为 Apache 的 www 目录（在我的机器上是 c:\www）。现在单击 File &gt; New &gt; Project。会弹出 New Project 向导。双击 PHP 文件夹并选择 PHP Project。单击 Next，输入项目名称 debugArticle，并单击 Finish。
如果把 Web 服务器设置为在端口 80 上侦听，那么不需要做任何修改。否则，请转到 Navigator 窗口，在 PHP 项目 debugArticle 上右击，选择 Properties，然后单击 PHP Project Settings。单击 Configure Workspace Settings 然后修改合适的 localhost 或者添加 Web 服务器侦听的端口（例如 http://localhost:8080）。单击 Apply 完成设置。
Navigator 窗口应当显示项目和一个 .project 文件。在项目上右击，就像前面做的那样，只是这次选择 New &gt; PHP File。用想要创建的 PHP 文件的名称 test3.php 替换 *.php，然后单击 Finish。在 Eclipse IDE 中应当出现一个新文件。可能需要导航到窗口底部的 PHP 浏览器来查看 PHP 文件的当前输出（参见图 5）。
图5：Eclipse 的 PHPEclipse 插件

498)this.style.width=498;}">
注意，只有 Windows 的用户可以像清单 5 所示的那样使用 PHP 浏览器。通过打开独立浏览器窗口并把浏览器指向测试脚本所在目录，也可以使用同样的功能。
现在来演示这个应用程序，证明它的强大能力。

在 “使用调试器” 一节中，将学习如何用 Eclipse、PHPEclipse 和前面下载的调试器 PHP 扩展来调试 PHP 应用程序。先从学习如何使用它的语法解析功能开始。

语法解析和加下划线
先从查看 PHPEclipse 如何提供帮助调试 PHP 应用程序的实时语法解析功能开始。要看这个特性的实际应用，先从在 Eclipse 中定义 test3.php 开始，如下所示。 






&lt;?php 
print(,"Hello World!"); 
?&gt;


注意，在清单 4 中加下划线的两个字符在 Eclipse 中加了下划线，提示语法不正确。按 Ctrl+S 保存文件，会在 Eclipse 中显示解析错误：在代码中与解析错误对应的行上会加上红 “x”，如图 6 所示。
图6：语法错误强调

498)this.style.width=498;}">
现在演示 PHP 浏览器。这个窗口提供了当前 PHP 脚本的预览，如图 6 所示。
从上面定义的 test3.php 中删除逗号（,）。按 Ctrl+S 保存文件，然后观察 PHP 浏览器窗口的更新，显示了 Hello World（参见图 7）。
图7：在PHPEclipse中预览PHP脚本

498)this.style.width=498;}">
下面是用调试器在 PHP 中设置断点。

[page]

使用调试器
使用调试器，可以设置断点并查看 PHP 代码到所设断点之前的浏览器输出。然后可以继续代码的执行并查看到下一断点之前的浏览器输出，然后再到下一个，直到 PHP 脚本完成。
现在把 “设置” 一节中在 php.ini 中注释掉的行取消注释，并重新启动 Apache。现在装入了调试器，Eclipse 能够和它挂上了。
现在在 Eclipse 中设计调试环境。请创建新的 test4.php 文件，先保持为空。现在单击 Run &gt; Debug。在左侧面板中选择 PHP DBG Script，并单击 New。现在转到 File 选项卡，输入当前项目 debugArticle 以及想要调试的文件 test4.php。现在转到 Environment 选项卡，然后再到 Interpreter 子选项卡。在 PHP 的安装目录中找到 php.exe 文件（我的是 c:\apps\php5.0.3\php.exe）。现在单击 Remote Debug 子选项卡，选择 Remote Debug，如果没有使用 Windows，请取消 “Open with DBGSession URL in internal browser box” 复选框。把 Remote Source 路径设置成与要测试的 PHP 脚本的绝对路径（不是 Web 路径）相同（我的设置是 c:\www\debugArticle\test4.php）。现在单击 Debug。
现在应当装入 Debug 透视图，如图 8 所示。否则，请单击 Window &gt; Open Perspective &gt; Other，并选择 Debug。
图8：Eclipse 中的 Debug 透视图

498)this.style.width=498;}">
现在可以设置断点了。
对于本文中使用的插件和扩展的版本，断点功能是必需的，因为 PHP 在把输出发送到浏览器之前会缓冲它。除此之外，需要做的不仅仅是设置一个断点把当前显示数据刷新到 Web 浏览器，所以要像下面和图 8 所示那样定义 test4.php。

&nbsp;

清单4：设置和创建断点 






&lt;?php 
function break-point(){ 
    ob_flush(); 
    flush(); 
    sleep(.1); 
    debugBreak(); 
} 
print("This will get shown first, "); 
print("as will this&lt;br&gt;"); 
breakpoint(); 
print("This won't get shown until after "); 
print("continuing the break-point&lt;br&gt;"); 
breakpoint(); 
print("END!"); 
? 


breakpoint() 函数会把缓冲的输出和其他缓冲的数据刷新到 Web 浏览器。对 sleep(.1) 的调用是必需的，这样代码中止于 debugBreak() 之前，服务器才有足够的时间把数据刷新到 Web 浏览器，这个函数是前面下载的 PHP 调试器扩展的内部函数。这样，调用 breakpoint() 会把 HTML 块、print() 和 echo() 语句的数据刷新到浏览器，然后中止代码执行。
在像清单 4 那样编写完代码之后，可以打开浏览器并指向 test4.php，或者可以查看 PHP 浏览器窗口（我的是 http://localhost/debugArticle/test4.php）。每次输入和保存文件时，在 PHP 浏览器窗口中就已经启动了调试序列。如果不使用 Windows，请通过浏览器查看 test4.php。在保存了文件之后，用 F8 或单击 Run &gt; Resume 继续代码执行。持续这么做，直到最后一行输出是 END! 为止（参见图 9、10 和 11）。
图9：初始的到第一个断点的 PHP 浏览器输出

498)this.style.width=498;}">
请注意图 9 中的 Debug 窗口如何把执行显示为挂起的。

[page]
图10：第一个断点之后到第二个断点之前的 PHP 浏览器输出

498)this.style.width=498;}">
图 10 的 Debug 窗口仍然把执行显示为挂起，而第二组数据显示在 PHP 浏览器中。
图11：完整的 PHP 浏览器输出

498)this.style.width=498;}">
注意，图 11 的 Debug 窗口中的代码不再挂起，整个脚本已经执行，如图 11 中的 PHP 浏览器所示。
既然已经看到了用 PHPEclipse 和调试器扩展进行开发的优势，那么很难想像没有它会怎么样。
结束语
现在已经向 PHP 的调试技术集中添加了错误报告的运用、print 语句、PHPEclipse 和调试器扩展，您可以通过减少每行代码的错误数量，成为更有效的 PHP 编码人员。请参阅 参考资料 获得一些 PHP 教程，可以在上面测试这些新技能。
]]></description>
		</item>
		<item>
			<title>基于PHP的AJAX技术实现文件异步上传</title>
			<link>http://www.kingmx.com/article.php?id=15205</link>
			<pubDate>2007-4-19</pubDate>
			<description><![CDATA[
异步的文件上传是在现代的AJAX实现的Web应用里面经常要遇到，必须解决的问题。但是标准的AJAX类（XmlHttpRequest）无法实现传输文件的功能。因此，这里讨论的内容就是如何在AJAX的技术的基础之上构建异步的文件上传功能。在这个功能当中需要使用到内置的框及（IFRAME）来传输文件。这个功能实现的效果是页面在上传文件的时候，用户还可以使用该页面并且填写文件描述。 
　　这个例子是我们引用AJAX的经典案例进行分析的。
　　系统环境

　　· 较新版本的浏览器。例如Opera，Firefox或者 Internet Explorer。 
　　· PHP 4.3.0 或更高版本 
　　· PHP 5 版本
　　· PHP 中的 'short_open_tag' 选项开启(否则会发生解析错误)。
　　功能分析
　　通过内置的IFRAME（框架）进行文件上传。具备包括三个部分组成。
　　· 在页面中间有一个简单的＜form...表单，表单只包含了＜input type="file" ... ＞控件。这个表单的目标链接就是一个隐藏得IFRAME(通过 CSS的风格" display: none;"实现)并且表单里面唯一一个控件的OnChange事件用来触发JavaScript函数。这个函数的作用是检查用户提交的扩展名，然后提交表单。 
　　· 在服务器端用PHP编写了一个处理过程（用FILEFRAME坐注释了）。这个处理过程用来把从客户端上传的文件进行检查后保存在服务器，并且通过Javascript代码的形式返回给用户。返回给用户的Javascript脚本通过"parent.window.document"更改了用户现在正在查看的页面，设置了文件的名称并启用了让用户提交表单的按钮。启用按钮的操作是通过getElementById函数实现的。
　　· 在主页面还有一个表单，它包含了用户提交的描述和隐藏的文件名。用户可以在文件上传的同时填写文件的描述。当文件上传结束以后，用户点击按钮，就可以看上传以后返回给用户的文件信息了。（通过返回来的文件名和用户输入的描述构成文件信息）。
　　可能你会说这么操作不符合常理：文件在用户确认之前就已经被提交了。如果用户没有提交的话，情况会如何呢。你可以自己在扩展处理被用户放弃的文件。 
　　这个例子把文件存储在一个文件系统的目录下。你需要在脚本开始运行的时候配置下这个目录，具体的包含这个目录信息的变量是$upload_dir 和$web_upload_dir。这里有一个对目录是否可写的权限检查。
　　这里我们用到了以下几个PHP函数：
　　· move_uploaded_file - 转移一经上传到服务器的文件 
　　· fopen - 打开文件 
　　· fwrite - 把内容写入文件 
　　· fclose - 关闭文件 
　　· str_replace - 替换字符串 
　　· filesize - 返回文件大小 
　　· filemtime - 返回处理时间
　　你可以通过手册查到这些函数如果使用。请注意要把HTM(＜, ＞, &amp;)标记替换为(&amp;lt;, &amp;gt; 和 &amp;amp;). 
[page]
&nbsp;&nbsp; 源代码




＜?php
$upload_dir = "/var/www/anyexample/aeu"; // 文件存储的路径
$web_upload_dir = "/aeu"; // 文件在Web目录下的路径
$tf = $upload_dir.'/'.md5(rand()).".test";
$f = @fopen($tf, "w");
if ($f == false) 
die("Fatal error! {$upload_dir} is not writable. Set 'chmod 777 {$upload_dir}'
or something like this");
fclose($f);
unlink($tf);
//处理上传的文件
if (isset($_POST['fileframe'])) 
{
　$result = 'ERROR';
　$result_msg = 'No FILE field found';
　if (isset($_FILES['file'])) // 从浏览器接受文件
　{
　　if ($_FILES['file']['error'] == UPLOAD_ERR_OK) // 没有错误
　　{
　　　$filename = $_FILES['file']['name']; // 文件名 
　　　move_uploaded_file($_FILES['file']['tmp_name'], $upload_dir.'/'.$filename);
　　　// 处理的主过程-转移文件到 $upload_dir 
　　　$result = 'OK';
　　}
　　elseif ($_FILES['file']['error'] == UPLOAD_ERR_INI_SIZE)
　　　$result_msg = 'The uploaded file exceeds the upload_max_filesize directive in php.ini';
　　else 
　　　$result_msg = 'Unknown error';
　}
　echo '＜html＞＜head＞＜title＞-＜/title＞＜/head＞＜body＞';
　echo '＜script language="JavaScript" type="text/javascript"＞'."\n";
　echo 'var parDoc = window.parent.document;';
　'
　if ($result == 'OK')
　{
　　echo 'parDoc.getElementById("upload_status").value = "file successfully uploaded";';
　　echo 'parDoc.getElementById("filename").value = "'.$filename.'";';
　　echo 'parDoc.getElementById("filenamei").value = "'.$filename.'";';
　　echo 'parDoc.getElementById("upload_button").disabled = false;';
　}
　else
　{
　　echo 'parDoc.getElementById("upload_status").value = "ERROR: '.$result_msg.'";';
　}
　echo "\n".'＜/script＞＜/body＞＜/html＞';
　exit();
}
function safehtml($s)
{
　$s=str_replace("&amp;", "&amp;amp;", $s);
　$s=str_replace("＜", "&amp;lt;", $s);
　$s=str_replace("＞", "&amp;gt;", $s);
　$s=str_replace("'", "&amp;apos;", $s);
　$s=str_replace("\"", "&amp;quot;", $s);
　return $s;
}
if (isset($_POST['description']))
{
　$filename = $_POST['filename'];
　$size = filesize($upload_dir.'/'.$filename);
　$date = date('r', filemtime($upload_dir.'/'.$filename));
　$description = safehtml($_POST['description']);
　$html =＜＜＜END
　＜html＞＜head＞＜title＞{$filename} [uploaded by IFRAME Async file uploader]＜/title＞＜/head＞
　＜body＞
　　＜h1＞{$filename}＜/h1＞
　　＜p＞This is a file information page for your uploaded file. Bookmark it, or send to anyone...＜/p＞
　　＜p＞Date: {$date}＜/p＞
　　＜p＞Size: {$size} bytes＜/p＞
　　＜p＞Description: 
　　＜pre＞{$description}＜/pre＞
　　＜/p＞
　　＜p＞＜a href="{$web_upload_dir}/{$filename}" style="font-size: large;"＞download file＜/a＞＜br＞
　　＜a href="{$PHP_SELF}" style="font-size: small;"＞back to file uploading＜/a＞＜br＞
　　＜a href="{$web_upload_dir}/upload-log.html" style="font-size: small;"＞upload-log＜/a＞＜/p＞
　　＜br＞＜br＞Example by ＜a href="http://www.anyexample.com/"＞AnyExample＜/a＞
　＜/body＞＜/html＞
　END;
　
　$f = fopen($upload_dir.'/'.$filename.'-desc.html', "w");
　fwrite($f, $html);
　fclose($f);
　$msg = "File {$filename} uploaded, 
　＜a href='{$web_upload_dir}/{$filename}-desc.html'＞see file information page＜/a＞";
　$f = fopen($upload_dir."/upload-log.html", "a");
　fwrite($f, "＜p＞$msg＜/p＞\n");
　fclose($f);
　setcookie('msg', $msg); 
　header("Location: http://".$_SERVER['HTTP_HOST'].$PHP_SELF); 
　exit(); 
} 
if (isset($_COOKIE['msg']) &amp;&amp; $_COOKIE['msg'] != '') 
{ 
　if (get_magic_quotes_gpc()) 
　　$msg = stripslashes($_COOKIE['msg']); 
　else
　　$msg = $_COOKIE['msg'];
　　setcookie('msg', ''); 
} 
?＞
＜!-- Beginning of main page --＞
＜html＞＜head＞
＜title＞IFRAME Async file uploader example＜/title＞
＜/head＞
＜body＞
＜?php 
　if (isset($msg)) 
　　echo '＜p style="font-weight: bold;"＞'.$msg.'＜/p＞';
?＞ 
＜h1＞Upload file:＜/h1＞
＜p＞File will begin to upload just after selection. ＜/p＞
＜p＞You may write file description, while you file is being uploaded.＜/p＞
＜form action="＜?=$PHP_SELF?＞" target="upload_iframe" method="post" enctype="multipart/form-data"＞
　＜input type="hidden" name="fileframe" value="true"＞
　＜!-- Target of the form is set to hidden iframe --＞
　＜!-- From will send its post data to fileframe section of this PHP script (see above) --＞
　＜label for="file"＞text file uploader:＜/label＞＜br＞
　＜!-- JavaScript is called by OnChange attribute --＞
　＜input type="file" name="file" id="file" onChange="jsUpload(this)"＞
＜/form＞
＜script type="text/javascript"＞
/* This function is called when user selects file in file dialog */
function jsUpload(upload_field)
{
　// this is just an example of checking file extensions
　// if you do not need extension checking, remove 
　// everything down to line
　// upload_field.form.submit();
　
　var re_text = /\.txt|\.xml|\.zip/i;
　var filename = upload_field.value;
　/* Checking file type */
　if (filename.search(re_text) == -1)
　{
　　alert("File does not have text(txt, xml, zip) extension");
　　upload_field.form.reset();
　　return false;
　}
　upload_field.form.submit();
　document.getElementById('upload_status').value = "uploading file...";
　upload_field.disabled = true;
　return true;
}
＜/script＞
＜iframe name="upload_iframe" style="width: 400px; height: 100px; display: none;"＞
＜/iframe＞
＜!-- For debugging purposes, it's often useful to remove
"display: none" from style="" attribute --＞
＜br＞
Upload status:＜br＞
＜input type="text" name="upload_status" id="upload_status" 
value="not uploaded" size="64" disabled＞
＜br＞＜br＞
File name:＜br＞
＜input type="text" name="filenamei" id="filenamei" value="none" disabled＞
＜form action="＜?=$PHP_SELF?＞" method="POST"＞
　＜!-- one field is "disabled" for displaying-only. Other, hidden one is for sending data --＞
　＜input type="hidden" name="filename" id="filename"＞
　＜br＞＜br＞
　＜label for="photo"＞File description:＜/label＞＜br＞
　＜textarea rows="5" cols="50" name="description"＞＜/textarea＞
　＜br＞＜br＞
　＜input type="submit" id="upload_button" value="save file" disabled＞
＜/form＞
＜br＞＜br＞
＜a href="＜?=$web_upload_dir?＞/upload-log.html"＞upload-log＜/a＞
＜br＞＜br＞＜br＞
Example by ＜a href="http://www.anyexample.com/"＞AnyExample＜/a＞
＜/body＞
＜/html＞

　　以上的讲解就是提供一种思路供大家参考。大家也可以根据自己的需求进行相应的优化。
]]></description>
		</item>
		<item>
			<title>缺陷月项目启动 披露PHP脚本语言漏洞</title>
			<link>http://www.kingmx.com/article.php?id=15204</link>
			<pubDate>2007-4-19</pubDate>
			<description><![CDATA[一名安全研究人员启动了一个新项目，披露PHP脚本语言漏洞。 
　　名为Month of PHP Bugs的这一项目的启动时间是上周四。据该项目的网站称，迄今为止，已经披露了5个缺陷，其中一些缺陷可能使运行PHP的系统的安全性受到影响。

　　知名PHP安全专家埃塞在该项目的网站上表示，这一项目旨在提高PHP的安全性。他写道，披露的缺陷将主要是PHP内核而非PHP语言中的缺陷。

　　PHP是一种被广泛用来创建动态Web网页的脚本语言。据安全新闻网站Security Focus提供的统计数字显示，在2006年报告的总缺陷中，用PHP编写的应用软件占了43%。

　　与过去数个月中启动的其它“缺陷月”活动不同的是，Month of PHP Bugs不仅仅只包含新发现的缺陷，它披露的一些缺陷可能已经得到修复，许多缺陷可能已经被报告给PHP安全团队。

　　Month of PHP Bugs与其它旨在披露软件中缺陷的项目类似。支持这些项目的研究人员都表示，他们希望提高系统的安全性，被公开披露的缺陷将更快地得到修正。
]]></description>
		</item>
		<item>
			<title>php中文本数据翻页（留言本翻页）</title>
			<link>http://www.kingmx.com/article.php?id=15126</link>
			<pubDate>2007-3-13</pubDate>
			<description><![CDATA[在mysq中介绍翻页的文章不少,而文本数据表格式的翻页介绍的很少，这里我就简单的说一下翻页 
&nbsp;&nbsp; 
&nbsp;&nbsp;主要介绍以下翻页思想 
&nbsp;&nbsp;1、留言本的翻页 
&nbsp;&nbsp;2、文本论坛的翻页 
&nbsp;&nbsp; 
&nbsp;&nbsp;———————————————————————— 
&nbsp;&nbsp;留言本的翻页： 
&nbsp;&nbsp;—————————————————————————————— 
&nbsp;&nbsp;这个在文本数据表中的翻页是最简单的翻页，这样说明一下 
&nbsp;&nbsp; 
&nbsp;&nbsp;golbal file 
&nbsp;&nbsp; Data.dat --- NOTE FILE USE 
&nbsp;&nbsp; user.dat --- Forum File use 
&nbsp;&nbsp;Data.dat 
&nbsp;&nbsp;__________________________________________________________________ 
&nbsp;&nbsp;[1] [POSTUSER] [TITLE] [MEM] [POSTTIME] [IP] 
&nbsp;&nbsp;[2] [POSTUSER] [TITLE] [MEM] [POSTTIME] [IP] 
&nbsp;&nbsp;[3] [POSTUSER] [TITLE] [MEM] [POSTTIME] [IP] 
&nbsp;&nbsp;[4] [POSTUSER] [TITLE] [MEM] [POSTTIME] [IP] 
&nbsp;&nbsp;[5] [POSTUSER] [TITLE] [MEM] [POSTTIME] [IP] 
&nbsp;&nbsp; 
&nbsp;&nbsp;说明： 
&nbsp;&nbsp; 其中的[1,2,3,4,5....]是我自己添加进去的，主要是为了大家更好的理解 
&nbsp;&nbsp; 
&nbsp;&nbsp;index.php source:. 
&nbsp;&nbsp; 
&nbsp;&nbsp;__________________________________________________ 
&nbsp;&nbsp; 
&nbsp;&nbsp;---====BOF====--- 
&nbsp;&nbsp;&lt;? 
&nbsp;&nbsp;$file = "data.dat"; //数据文件 
&nbsp;&nbsp;if(file_exits($file)){ //容错处理，防止无数据文件存在 
&nbsp;&nbsp; $fp=fopen($file,"w+"); 
&nbsp;&nbsp; fclose($fp); 
&nbsp;&nbsp; unset($fp); 
&nbsp;&nbsp;} 
&nbsp;&nbsp;$listnumber = 20; //每页显示条数 
&nbsp;&nbsp;$fp = file($file); //读取数据到内容中 
&nbsp;&nbsp;$number = count($fp); //计算总数据量 
&nbsp;&nbsp;$pagenumber = floor($number/$listnumber)+1; 
&nbsp;&nbsp;if($number&lt;1){ 
&nbsp;&nbsp; print "暂时无记录，欢迎留言"; 
&nbsp;&nbsp; /*+--------------------------------+ 
&nbsp;&nbsp; |在这里打印FORM表单或连接到表但的| 
&nbsp;&nbsp; | URL， | 
&nbsp;&nbsp; +--------------------------------+*/ 
&nbsp;&nbsp;}else{ 
&nbsp;&nbsp; if(empty($_POST["page"])){ //这段IF...ELSE...是为了兼容php4.20的默认设置，防止出现无效的全局变量而写的 
&nbsp;&nbsp; $page = 0; //因为是从数据文本读出来的，保存在数组中，有个O下标 
&nbsp;&nbsp; }else{ 
&nbsp;&nbsp; $page = $_POST["page"] 
&nbsp;&nbsp; } 
&nbsp;&nbsp; 
&nbsp;&nbsp; if($page&lt;0 || $page&gt;pagenumber){ //检错处理，当页面参数跳出总页面或小于首页(0)的时候，将返回到第一页 
&nbsp;&nbsp; $page=0; 
&nbsp;&nbsp; } 
&nbsp;&nbsp; 
&nbsp;&nbsp; $startnote = $page*$listnumber; //开始记录位置 
&nbsp;&nbsp; $endnote = $startnote+$listnumber; //结束记录位置 
&nbsp;&nbsp; 
&nbsp;&nbsp; //for($int_a=$startnote;$int_a&lt;$endnote;$int_a++){ //排序显示类似ASC模式 
&nbsp;&nbsp; 
&nbsp;&nbsp; pirnt "&lt;table&gt;" 
&nbsp;&nbsp; 
&nbsp;&nbsp; for($int_a=$endnote;$int_a&gt;=$startnote;$int_a--){ //排序显示类似DESC模式 
&nbsp;&nbsp; $info=explode("\t",$fp[$int-a]); //切割数据获得每条记录的详细数据我这里是用了一个TAB键分割 
&nbsp;&nbsp; print "&lt;tr&gt;&lt;td&gt;用户:$info[1] 标题$info[2] 发言内容：$info[3] 发布时间:$info[4] IP：$info[5]"; 
&nbsp;&nbsp; } 
&nbsp;&nbsp; 
&nbsp;&nbsp; $prevpage = $page-1; //上一页的PAGE数 
&nbsp;&nbsp; $nextpage = $page+1; //下一页的page数 
&nbsp;&nbsp; 
&nbsp;&nbsp; print "&lt;tr&gt;&lt;td&gt; 
&nbsp;&nbsp; &lt;a href=\"$_SERVER["PHP_SELF"]?page=0\"&gt;首页&lt;/a&gt; 
&nbsp;&nbsp; &lt;a href=\"$_SERVER["PHP_SELF"]?page=$prevpage\"&gt;上一页&lt;/a&gt; 
&nbsp;&nbsp; &lt;a href=\"$_SERVER["PHP_SELF"]?page=$nextpage\"&gt;下一页&lt;/a&gt; 
&nbsp;&nbsp; &lt;a href=\"$_SERVER["PHP_SELF"]?page=$pagenumber\"&gt;尾页&lt;/a&gt; 
&nbsp;&nbsp; &lt;/table&gt;"; //这里您可以直接将页面的检测加到这里，那样给别人看的是舒服的，但是效果是一样的 
&nbsp;&nbsp; //例如：这里有可能出现20页出现 &lt;a href="index.php?page=21"&gt;下一页&lt;/a&gt; 或&lt;a href="index.php?page=-1"&gt; 
&nbsp;&nbsp;} 
&nbsp;&nbsp;?&gt; 
&nbsp;&nbsp;---====EOF====--- 
&nbsp;&nbsp; 
&nbsp;&nbsp; 
&nbsp;&nbsp;写的仓促，另外中间有不少因为考虑到使用PHP4.20所以就改变了一下，比如说PHP_SELF已经采用_SERVER["PHP_SELF"]等 ]]></description>
		</item>
		<item>
			<title>自动跳转中英文页面代码</title>
			<link>http://www.kingmx.com/article.php?id=15125</link>
			<pubDate>2007-3-13</pubDate>
			<description><![CDATA[
PHP网页根据来访者的浏览器语言不同自动跳转中英文页面 
当来访者浏览器语言是中文就进入中文版面
国外的用户默认浏览器不是中文的就跳转英文页面
PHP代码:

&lt;?
&nbsp; &nbsp;$lan = substr($HTTP_ACCEPT_LANGUAGE,0,5);
&nbsp; &nbsp;if ($lan == "zh-cn")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;print("&lt;meta http-equiv='refresh' content = '0;URL = gb/index.htm'&gt;");
&nbsp; &nbsp;else
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;print("&lt;meta http-equiv='refresh' content = '0;URL = en/index.htm'&gt;");
?&gt;
HTML网页根据来访这的浏览器语言不同自动跳转多语言页面 
在 之间加入如下代码:

&lt;script&gt; 
var type=navigator.appName 
if (type=="Netscape") 
var lang = navigator.language 
else 
var lang = navigator.userLanguage 
//cut down to first 2 chars of country code 
var lang = lang.substr(0,2) 
// 英语
if (lang == "en") 
window.location.replace('url') 
// 简体中文
else if (lang == "zh-cn") 
window.location.replace('url') 
// 繁体中文
else if (lang == "zh-tw") 
window.location.replace('url') 
// 德语
else if (lang == "de") 
window.location.replace('url') 
// 除上面所列的语言
else 
window.location.replace('url')
&lt;/script&gt;
]]></descript