PHP最初是一个用Perl编写的简单的CGI包装器。我在合同之间的空闲时间里用了一下午的时间写了它,当时我需要一个快速的工具来了解谁在阅读我的在线简历。它从未打算超越我个人的使用。我放置简历的Web服务器极其超负荷,并且经常出现进程分叉问题。我用C重写了Perl包装器,以消除每次访问我的简历时都必须分叉Perl的相当大的开销。
最终,同一Web服务器上的其他人发现了我的包装器,并询问他们是否可以使用它。然后,就像不可避免地会发生的那样,他们开始要求更多功能。我添加了更多功能,最终整理了一个半完整的发行版,其中包括文档、邮件列表和常见问题解答。这个第一个软件包的名称是个人主页工具(Personal Home Page Tools),后来变成了个人主页构建工具包(Personal Home Page Construction Kit)。
与此同时,我开始使用数据库,并编写了一个工具,可以轻松地将SQL查询嵌入到网页中。它基本上是另一个解析SQL查询的CGI包装器,它可以轻松创建基于这些查询的表单和表格。这个工具名为FI(表单解释器,Form Interpreter)。
PHP/FI 2.0版本是对这两个软件包的完整重写,并将它们组合成一个程序。它现在已经发展到嵌入在HTML文件中的简单编程语言的程度。最初的首字母缩写词PHP仍然保留了下来,尽管现在已经不太贴切了。如今,PHP/FI更多地用于整个网站,而不是用于小型个人主页设置。无论名称如何,它都通过允许您将简单的脚本直接放置在HTML文件中,消除了对许多小型Perl cgi程序的需求。由于消除了多次分叉Perl的开销,这加快了网页的整体性能。它还可以通过将网页的所有组件都放在单个HTML文件中来简化大型网站的管理。通过支持各种数据库,它还可以轻松开发支持数据库的网页。许多人发现嵌入式性质比试图创建单独的HTML和CGI文件更容易处理。
PHP 3.0版本是另一个重写版本。如果您刚开始使用PHP,我建议您从3.0版本开始,而不是继续使用2.0版本。PHP3很快就会取代PHP/FI 2.0,所有开发工作现在都集中在PHP3上。PHP/FI 2.0中剩余的错误不太可能被修复,除非它们很简单。有关PHP3的更多信息,请访问http://www.lerdorf.on.ca/php3。
在本文档中,所有对PHP、FI或PHP/FI的引用都指的是同一件事。PHP和FI之间的区别只是一个概念上的区别。两者都是从相同的发行版构建的。当我构建没有任何访问日志或访问限制支持的软件包时,我将我的二进制文件称为FI。当我使用这些选项构建时,我称之为PHP。
如果您完全没有Unix经验,您可能需要四处询问一下,看看是否有了解一些Unix知识的人可以帮助您完成安装过程。我已经尽一切努力使其尽可能简单,但是由于该软件非常复杂并且依赖于许多不同的组件,因此假设它在所有系统上都能顺利运行是不现实的。您可能需要身边有人非常了解目标系统的细节。
- 您的服务器能否运行GET和POST方法的CGI程序?
如果您安装的是Apache模块版本,则此信息不相关。如果不能,则无法使用此软件包。在许多公共ISP上,CGI程序要么被禁止,要么受到严格限制。如果您的系统上出现这种情况,请与您的系统管理员联系,并请他们查看此软件包,看看他们是否会为您安装它。
- 如果您的系统上安装了mSQL,则需要知道此安装的基本目录。
- 如果您的系统上安装了Postgres95或PostgreSQL,则需要知道此安装的基本目录。
- 如果您打算将日志和访问配置文件存储在NFS挂载的目录中,并且您的系统不提供NFS文件锁定,则需要在src/Makefile中手动定义NFS_HACK变量,并且您可能需要使用略微修改版本的gdbm库。有关此方面的更多信息,请参阅doc目录中的**nfs_hack.txt**文件。
- 请注意,如果您不想使用PHP来跟踪对您页面的访问,请不要将此选项编译到二进制文件中。您还应该忽略访问限制代码。包含这些选项会带来相当大的开销。
- 如果您正在安装Apache模块版本,则需要知道Apache源代码目录的位置。
步骤1。
运行安装程序:./install
系统会问您一些问题。如果您不理解所提的问题,只需按回车键即可。在大多数系统上,默认选择应该是安全的。但这不适用于要求您为配置和日志文件指定目录的问题。选择任何httpd(通常是“nobody”)具有写权限的目录。您可以手动在某个地方创建此目录,只需chown nobody directory
。
步骤2。
进入src目录:cd src
查看php.h文件。此处可以设置许多编译时选项。
步骤3。
键入:make
这将创建名为php.cgi的可执行程序文件(默认情况下),或者如果您正在安装Apache模块,它将创建一个libphp.a文件。
步骤4。(如果您没有安装Apache模块版本)
将 **php.cgi** 二进制文件复制到系统的 cgi-bin 目录。如果您无权执行此操作,并希望将其安装在您自己的个人目录中,您可以这样做,但应使用以下命令设置可执行文件的 setuid 位:chmod u+s /path/php.cgi
如果您不设置二进制文件的 setuid 位,则该二进制文件创建的任何文件都将由 Web 服务器运行的用户 ID 拥有。如果这是可以接受的,则可以安全地关闭 setuid 位。
步骤 4。(如果您正在安装 Apache 模块版本)
切换到您的 Apache 源代码目录,其中应该已复制了 *mod_php.c* 和 *mod_php.h* 文件。如果由于权限问题通常不会发生这种情况,则手动将这两个文件复制到那里。编辑您的 Apache 配置文件并添加在 **步骤 3** 结尾生成的 EXTRA_LIBS 行。并添加
Module php_module mod_php.o
到文件的最后一行。然后键入:**./Configure**,然后键入 **make** 来重新构建您的 Apache httpd 二进制文件。安装此二进制文件。
接下来,您需要编辑 Apache conf/srm.conf 文件并添加一行,例如
AddType application/x-httpd-php .phtml
这定义了一种新的 MIME 类型 application/x-httpd-php,它将触发 PHP 模块来解析任何以 *phtml* 扩展名结尾的文件。您可以为此选择任何您喜欢的扩展名。
您可能不希望允许每个人都运行 PHP 解析的文件。您可以将上面的 AddType 行放在 access.conf 文件中的 <Location /path>....</Location> 指令内,以仅允许服务器上某些目录中的 PHP 解析的文档。
现在您可以重新启动您的 httpd 服务器了。有关配置 PHP 模块的更多详细信息,请参见 Apache 模块说明。
安装完成后,您可以通过在浏览器中输入类似于以下内容的 URL 来测试您的可执行文件是否有效
http://your.site.domain/cgi-bin/php.cgi
这应该会显示一个页面,其中包含版本号以及其他各种有用的信息。
要测试 Apache 模块版本,请创建任何具有 .phtml 扩展名的文件,并将类似于:<?phpinfo()> 的标签放在文件中,看看它是否被解析。
要在现有的 HTML 文件上实际使用该软件,您可以简单地将文件的路径附加到上面的 URL。例如:
http://your.site.domain/cgi-bin/php.cgi/path/file.html
您应该查看本文档的 CGI 重定向 部分。通过重定向运行 PHP/FI 意味着您可以自动拥有类似于 *http://your.site.domain/file.phtml* 的 URL 由 PHP/FI 解析。
这不适用于 Apace 模块用户。
如果您通过 PHP/FI 运行页面,您会注意到第一件事是它会添加一个页脚,其中包含有关访问页面次数的信息(如果您已将访问日志记录编译到二进制文件中)。这只是 PHP/FI 可以为您做的很小一部分。它还扮演着表单解释器 cgi 的另一个非常重要的角色,这就是名称中 FI 部分的含义。例如,如果您在一个网页上创建一个表单,您需要一些东西来处理该表单中的信息。即使您只想将信息传递到另一个网页,也必须让 cgi 程序为您执行此操作。PHP/FI 使获取表单数据并对其进行操作变得极其容易。
一个简单的例子
假设您有一个表单
<FORM ACTION="/cgi-bin/php.cgi/~userid/display.html" METHOD=POST>
<INPUT TYPE="text" name="name">
<INPUT TYPE="text" name="age">
<INPUT TYPE="submit">
</FORM>
然后,您的 display.html 文件可以包含类似以下内容:
<?echo "Hi $name, you are $age years old!<p>">
就这么简单!PHP/FI 会自动为表单中的每个表单输入字段创建一个变量。然后,您可以在 ACTION URL 文件中使用这些变量。
一旦您弄清楚如何使用变量,下一步就是开始在您的页面中使用一些逻辑流标签。例如,如果您想根据用户输入的内容显示不同的消息,则可以使用 if/else 逻辑。在上面的示例中,我们可以通过将 display.html 更改为根据用户输入的年龄显示不同的内容:
<? if($age>50); echo "Hi $name, you are ancient!<p>"; elseif($age>30); echo "Hi $name, you are very old!<p>"; else; echo "Hi $name."; endif; >
PHP/FI 提供了一种非常强大的脚本语言,它可以完成比上述简单示例演示的更多功能。有关更多信息,请参见关于 PHP/FI 脚本语言 的部分。
您还可以使用 PHP/FI 来配置允许访问您页面的用户。这是使用内置的配置屏幕完成的。例如,您可以使用它指定只有来自特定域的人才能查看您的页面,或者您可以创建一个规则来保护某些页面的密码。有关更多详细信息,请参见 访问控制 部分。
PHP/FI 还可以接收来自任何符合 RFC-1867 的 Web 浏览器的文件上传。此功能允许用户上传文本文件和二进制文件。借助 PHP/FI 的访问控制和逻辑函数,您可以完全控制谁可以上传以及上传文件后要对其执行的操作。有关更多详细信息,请参见 文件上传 部分。
PHP/FI 支持名为 mSQL 的数据库包。这允许您将信息放入数据库,并直接在 .HTML 文件中通过简单的嵌入式 SQL 查询访问此信息。向网页添加数据库后端从未如此简单。有关更多信息,请参见 mSQL 支持 部分。
PHP/FI 支持 Postgres95/PostgreSQL 数据库包。它支持在 .HTML 文件中嵌入 SQL 查询。有关更多信息,请参见 Postgres95/PostgreSQL 支持 部分。
PHP/FI 还支持 mysql 数据库包。它支持在 .HTML 文件中嵌入 SQL 查询。有关更多信息,请参见 mysql 支持 部分。
运行 PHP/FI 的一个好方法是将 cgi 重定向模块与 Apache 服务器一起使用。请注意,如果您使用的是 PHP/FI 的 Apache 模块版本,则无需担心重定向模块。有两个这样的重定向模块可用。一个是由 Dave Andersen <[email protected]> 开发的,它可以在 ftp://ftp.aros.net/pub/util/apache/mod_cgi_redirect.c 获取,另一个与 Apache 捆绑在一起,名为 mod_actions.c。这两个模块非常相似。它们在用法上略有不同。两者都经过测试,并且都与 PHP/FI 配合使用。
在撰写本文时(1996 年 4 月 20 日)的一个很大的警告是,当前的官方 Apache 版本 (1.0.5) 有一个严重的限制,它阻止 cgi 重定向请求具有任何与之关联的 post 方法数据。我已经追踪到这个问题并在我的 Apache 版本中修复了它,并且在 PHP 首页 上的 文件存档 中有一个官方补丁。
Apache 1.0.x 的第二个相当大的警告是,它在大多数架构上不能正确对齐双精度类型。在使用 mod_php 时,您可能会发现您的 httpd 会出现奇怪的总线错误,请升级到 Apache 1.1 或编辑 *alloc.c* Apache 源文件。在这个文件中,你会找到以下代码段
union align { /* Types which are likely to have the longest RELEVANT alignment * restrictions... we don't do much with doubles. */ char *cp; void (*f)(); long l; FILE *fp; };
您需要在此行中添加一个双精度数并重新编译您的 Apache 服务器。正确的代码块是
union align { /* Types which are likely to have the longest RELEVANT alignment * restrictions... we don't do much with doubles. */ char *cp; void (*f)(); long l; FILE *fp; double d; };
这些问题在 Apache 的后续版本中都已解决。
查看 Apache 文档,了解如何添加模块。通常,您将模块名称添加到名为 *Configuration* 的文件中。如果您想使用 mod_actions 模块,则要添加的行是
Module action_module mod_actions.o
如果您使用的是 mod_cgi_redirect.c 模块,请添加此行
Module cgi_redirect_module mod_cgi_redirect.o
然后编译您的 httpd 并安装它。要配置 cgi 重定向,您需要在您的 *mime.types* 文件中创建一个新的 mime 类型,或者您可以使用 *srm.conf* 文件中的 **AddType** 命令来添加 mime 类型。要添加的 mime 类型应类似于以下内容
application/x-httpd-php phtml
如果您使用的是 mod_actions.c 模块,则需要将以下行添加到您的 *srm.conf* 文件中
Action application/x-httpd-php /cgi-bin/php.cgi
如果您使用的是 mod_cgi_redirect.c,则应将此行添加到 *srm.conf* 中
CgiRedirect application/x-httpd-php /cgi-bin/php.cgi
不要尝试同时使用 mod_actions.c 和 mod_cgi_redirect.c。
安装并正确配置其中一个 cgi 重定向模块后,您可以通过将文件的扩展名设置为 **.phtml** 来指定要由 php/fi 解析的文件。此外,如果您将 **index.phtml** 添加到 *srm.conf* 文件中的 **DirectoryIndex** 配置行中,则如果您的索引文件名为 index.phtml,则目录中的顶级页面将由 php 自动解析。
您可以使用 Netscape Server CGI Redirection 模块自动重定向对具有给定扩展名的文件的请求,以由 PHP/FI 处理。此模块可在 PHP/FI 首页 上的 文件存档 中找到。包中的自述文件明确解释了如何将其配置为与 PHP/FI 一起使用。
NCSA 目前不支持模块,因此要使用此服务器进行 cgi 重定向,您需要修改服务器源代码。在 PHP/FI 文件存档 中可以找到使用 NCSA 1.5 执行此操作的补丁。
PHP/FI 的 CGI 版本**不会**读取目录中可能存在的任何 *.htaccess* 文件。这意味着如果您有使用标准 .htaccess 基于服务器的访问控制功能受保护的文件,则人们可以通过 PHP/FI 加载页面来绕过此安全性。请注意,对于 PHP/FI 的 Apache 模块版本,这不是问题。
CGI 版本的第二个问题是,如果将其放置在系统的 cgi-bin 目录中,只要运行它的用户 ID 具有访问权限,就可以用来查看系统上的任何文件。
这个问题有几个不同的解决方案。最简单的可能是使用 php.h 中的 **PATTERN_RESTRICT** 功能。这允许你定义允许 PHP/FI 解析的文件扩展名(或扩展名模式)。如果文件没有这个扩展名,并且有人试图用 PHP/FI 加载它,则会出现“访问被拒绝”的消息。
另一个解决方案是使用 PHP/FI 访问控制机制来模拟 .htaccess 文件中的访问控制设置。但是,将这些信息保存在两个地方可能会很繁琐,而且这两个系统并不共享所有相同的特性。
这个问题也可以通过文件权限来解决。可以将 PHP/FI 设置为以任何你希望的用户身份运行 setuid。然后,可以为 PHP/FI 要读取的文件赋予相应的权限,而对于 PHP/FI 不应读取的文件,应将其所有者更改为另一个用户 ID 并相应地更改其权限。
有关为提供 PHP 共享访问权限的站点的其他安全选项,请参阅 安全模式 部分。
PHP 的安全模式试图解决许多 ISP 面临的一个常见问题,即让所有用户运行 CGI 程序。使共享 CGI 访问更安全的一种常用机制是使用 cgi 包装器(例如 Apache 附带的 su_exec 实用程序)。当 PHP 作为模块运行时,这将不起作用,因为它不是可以设置 setuid 的单独进程。
它基于文件权限方案。简而言之,如果文件由尝试访问它的脚本的所有者拥有,或者如果文件位于由尝试访问它的脚本的所有者拥有的目录中,则允许访问。这里的一个需要注意的是,你必须确保你的操作系统不允许非 root 用户更改其文件的拥有者。许多较旧的 SysV 系统允许这样做。最常见的是 Irix。可以在 Irix 的操作系统级别更改此行为。
安全模式适用于每个可能存在安全风险的函数。以下是应用于每个相关函数的当前检查列表。在下面的列表中,PHP UID 指的是正在由 PHP 解析的当前文件所有者的用户 ID,而 HTTP UID 指的是 httpd 进程运行的用户 ID(通常是 nobody)。
如果你构建了 PHP/FI 的 CGI 版本,你可以从命令行使用它,只需键入:php.cgi filename
,其中 filename 是你想要解析的文件。你还可以通过使脚本的第一行看起来像这样来创建独立的 PHP/FI 脚本:
#!/usr/local/bin/php.cgi -q“-q”会抑制 HTTP 头的打印。如果愿意,你可以省略此选项。
PHP/FI 中的 HTTP 身份验证挂钩仅在其作为 Apache 模块运行时才可用。在 Apache 模块 PHP/FI 脚本中,可以使用 Header() 命令向客户端浏览器发送“需要身份验证”消息,从而使其弹出用户名/密码输入窗口。用户填写用户名和密码后,将再次调用包含 PHP/FI 脚本的 URL,并将变量 $PHP_AUTH_USER、$PHP_AUTH_PW 和 $PHP_AUTH_TYPE 分别设置为用户名、密码和身份验证类型。目前只支持“Basic”身份验证。
一个强制客户端在页面上进行身份验证的示例脚本片段如下所示:
<? if(!$PHP_AUTH_USER) { Header("WWW-authenticate: basic realm=\"My Realm\""); Header("HTTP/1.0 401 Unauthorized"); echo "Text to send if user hits Cancel button\n" exit; } else { echo "Hello $PHP_AUTH_USER.<P>"; echo "You entered $PHP_AUTH_PW as your password.<P>"; } >
你可能不希望只打印出 $PHP_AUTH_USER 和 $PHP_AUTH_PW,而是要检查用户名和密码的有效性。也许可以通过向数据库发送查询,或者在 dbm 文件中查找用户来实现。
注意那些有问题的 Internet Explorer 浏览器。它们似乎对标题的顺序非常挑剔。目前,在 HTTP/1.0 401 头之前发送 WWW-authenticate 头似乎可以解决问题。
为了防止有人编写一个脚本,该脚本揭示通过传统的外部机制进行身份验证的页面的密码,如果为该特定页面启用了外部身份验证,则不会设置 PHP_AUTH 变量。
但是请注意,上述方法并不能阻止控制未经身份验证的 URL 的人从同一服务器上的已验证 URL 窃取密码。可以取消定义 php.h 中的 PHP_AUTH_VARS 定义,以确保永远不会设置这些变量,从而禁用任何人使用 mod_php 来尝试窃取密码。
当以 Apache 模块的形式运行 PHP 时,你可以通过在要使用的头值开头添加 $req_ 来访问远程浏览器发送的请求头变量。如果请求名称包含 - 字符(例如 User-Agent),则需要将 - 映射到 _(下划线)。即将其引用为 $req_User_Agent。可以使用 phpinfo() 函数显示所有请求头。
例如:
< echo "$req_connection<br>"; echo "$req_host<br>"; >上述简单脚本可能会输出:
Keep-Alive www.host.com
将 PHP/FI 作为 Apache 模块运行是使用该软件包最有效的方法。作为模块运行意味着 PHP/FI 功能与 Apache 服务器的功能在一个程序中结合在一起。作为模块运行有很多优点:
从性能方面来看,它比传统的 CGI 程序快得多。实际上,当 PHP/FI 作为模块运行时,不会涉及 CGI。HTML 文件中的脚本代码由 Apache Web 服务器进程直接执行。
当作为模块运行时,在允许模块解析文件之前,首先应用在 Apache 配置文件中或私有 .htaccess 文件中定义的基于 httpd 的正常访问限制规则。或者,你还可以创建控制基于 httpd 的正常身份验证的 PHP/FI 脚本。请参阅 HTTP 身份验证。
由于解析器始终在 httpd 进程内处于活动状态,因此可以使用用于配置 httpd 进程的相同配置文件在启动时对其进行配置。甚至可以通过将 PHP 配置指令 放入 .htaccess 文件中,在每个目录的基础上配置模块。
对于有兴趣从 Apache 内部访问其函数的 C 程序员,PHP/FI 框架为 Apache 和 PHP 本身提供了一个非常简单的接口。向 PHP 添加一个函数并从解析的页面调用它,比从头开始编写整个 Apache 模块要容易得多。有关详细信息,请参阅本文档末尾的 向 PHP/FI 添加你自己的内部函数 部分。
以下指令可以放置在 srm.conf 文件中,或者放在 access.conf 中的 <Directory>...</Directory> 标记内,或者放在 access.conf 中的 <Location /path>...</Location> 标记内,或者放在单独的 .htaccess 文件中。为了使指令在 .htaccess 文件中工作,必须在 AllowOverride Apache 指令上设置 Options override,但 phpEngine 指令除外,它只能在 *.conf 文件中使用。
所有这些指令都是可选的。如果任何地方都没有指定指令,则将使用编译时默认值。
PHP/FI 可以编译成支持 FastCGI。在编译 PHP/FI 之前,您需要获取并编译适合您平台的 FCGI 开发套件。您还需要使 CGI 重定向 正确工作。然后按照 FastCGI 文档中的说明为您的平台配置 FastCGI。如果您在 Apache 服务器上使用 mod_fastcgi 模块,以下是分步说明
AddType application/x-httpd-fcgi .fcgi
AppClass /usr/local/etc/httpd/fcgi-bin/php.fcgi -processes 4
AddType application/x-httpd-fphp .fhtml
Action application/x-httpd-fphp /fcgi-bin/php.fcgi
现在,任何扩展名为 .fhtml 的页面都将交给已运行的 FastCGI php.fcgi 进程处理。php.fcgi 二进制文件仍然可以作为普通的 CGI 二进制文件工作,因此您可以从 php.cgi 到 php.fcgi 创建一个符号链接。
如果您没有使用 Apache,上述步骤将类似但并不完全相同。可在 PHP/FI 文件存档 中找到适用于 NCSA 和 Netscape 服务器的 CGI 重定向机制。
请注意,内置的基于 PHP/FI 的访问控制功能可能会在未来的版本中被取消。您应该认真考虑改用 Web 服务器自带的安全机制。
如果您在编译软件包时选择包含访问控制,则可以将 ?config 附加到任何 URL 以编辑访问控制文件。例如:
http://your.machine.domain/cgi-bin/php.cgi/path/file.html?config
您的配置密码最初将设置为您的用户 ID。如果您的用户 ID 不能用作您的密码,则可能意味着 PHP 无法读取 /etc/passwd 文件以找到您的用户 ID。如果是这种情况,则初始密码将设置为“php”。最好更改此密码。请注意,多个用户可以通过单个 PHP/FI 二进制文件维护他们自己的个人配置文件。
访问控制最初可能比较令人困惑。?config 屏幕分为多个部分。顶部部分用于更改密码,以确保只有知道此密码的人才能更改访问控制特性。在系统范围的安装中,每个用户都有自己的配置屏幕和自己的密码。
?config 屏幕的第二部分由多个表组成。每个表定义一个规则集。第一个规则集始终是默认规则集。如果页面没有为此页面专门定义规则集,则使用此默认规则集。在默认规则集之后,将遵循任意数量的特定规则集表。
要为特定文件添加规则集,请在浏览器中输入文件的 URL 并将 ?config 添加到 URL 的末尾。在出现的 ?config 屏幕上,您将看到已为此页面添加了规则集(如果之前不存在的话)。添加新的规则集时,它最初设置为与默认规则集相同。下图显示了两个简单的规则集。第一个是默认规则集,它只表示应记录来自所有域的命中,第二个是针对文件 /~rasmus/test.html(仅限该文件),来自“.edu”域的任何用户都将被拒绝访问。
要编辑规则集,请修改规则集内的字段,直到达到所需的配置,然后单击“提交更改”按钮。如果需要更多规则,请单击“添加规则”按钮,然后编辑添加的规则。
要删除规则,请选中规则右侧的复选框,然后单击“提交更改”按钮。屏幕将重新绘制,规则应消失。
请注意,您需要在模式字段中输入正则表达式。有关更多详细信息,请参阅本文档中关于正则表达式的部分。
访问日志记录是另一项可选功能,可以通过在安装脚本中回答“是”来在编译时启用。您可以将访问日志数据存储在 dbm 文件、mSQL 数据库或 mysql 数据库中。后两者功能更强大,但设置也更复杂一些。
要使用 dbm 文件存储访问日志,您需要指定一个可以写入日志文件的目录。如果 PHP 不存在,它将尝试创建此目录,但是为了确保它具有正确的权限,您可能希望在第一次运行 PHP 之前自行创建此目录。目录的权限应允许运行 PHP cgi 程序的用户 ID 对目录进行写入。
要使用 mSQL 或 mysql 数据库存储访问日志数据,您首先需要确保已在系统上安装并运行 mSQL 或 mysql。然后,您需要创建一个数据库。默认名称是“phpfi”,但这可以在 src/php.h 中更改。要为 mSQL 创建此数据库,请键入:
msqladmin create phpfi
或对于 mysql,键入:
mysqladmin create phpfi
然后对于 mSQL,编辑您的 msql.acl 文件并确保数据库的权限正确。以下内容应该足够:
database=phpfi read=* write=nobody,<your user id> access=local
对于 mysql,您需要确保 httpd 用户(通常为“nobody”)可以访问数据库。与 mSQL 不同,mysql 将访问控制数据存储在数据库中。假设权限为默认值,您只需执行以下命令:
echo "INSERT INTO user VALUES ('localhost','nobody','','Y','Y','Y','Y','Y','Y','Y','Y','Y');" | mysql mysql
不要忘记使用以下命令加载此新配置:
mysqladmin reload
对于您要存储日志数据的每个用户 ID,您都需要创建两个表。scripts 目录中的 msqllog shell 脚本将为您执行此操作。只需键入:
msqllog <user id>
或对于 mysql,键入:
mysqllog <user id>
脚本将创建相应的表。您可能需要编辑脚本以使其反映系统上存储位置。
您可能需要查看此脚本。它定义了日志表的字段大小。例如,如果您知道文件路径超过 64 个字符,则需要在 msqllog 或 mysqllog 文件中的 logN 和 lastN 表中增加文件名大小。
访问日志记录会存储有关页面每次“命中”的信息。然后可以通过检查这些日志文件来总结这些信息。软件包中包含一个示例日志文件汇总脚本。它是 examples
目录中的 log.html
文件。这是 dbm 日志文件分析器。mSQL 日志文件分析器称为 mlog.html
。mysql 日志文件分析器称为 mylog.html
。要运行它,请将其和其他 mlog.* 文件复制到 Web 服务器可以访问的目录,然后键入:
http://your.machine.domain/cgi-bin/php.cgi/path/mlog.html
或者,如果您使用的是 Apache 模块版本,则可以为脚本指定“.phtml”扩展名并使用以下命令调用它:
http://your.machine.domain/path/mlog.phtml
默认情况下,如果您使用已启用访问日志记录功能编译的 PHP,则您的页面将显示包含一些访问信息的页脚。您可能不想看到此页脚,但仍要记录命中次数。如果您运行的是 Apache,则可以在 Apache httpd.conf 或 .htaccess 文件中使用“phpShowInfo off”行关闭此页脚。如果您没有运行 Apache,则可以通过在 ?config 部分中为页面创建规则,或者通过向页面添加如下标签来关闭这些日志页脚:
<?setshowinfo(0)>
所有 CGI 包装器的一个常见问题是 HTTPD 程序将当前目录更改为存储正在加载内容的目录。对于 CGI 程序,当前目录设置为 CGI 程序所在的目录。这通常不是问题,除非涉及相对 URL。
相对 URL 是依赖于当前目录与当前 HTML 文件所在的目录相同的 URL。例如,如果我有 URL:
http://my.machine/~rasmus/file.html
实际的 HTML 文件可能是:
~rasmus/public_html/file.html
如果在 file.html
文件中我有标签:
<IMG SRC="pic.gif">
正常加载时,此 gif 文件应位于 ~rasmus/public_html/pic.gif
。但是,当通过 CGI 包装器使用类似 URL 加载时:
http://my.machine/cgi-bin/php.cgi/~rasmus/file.html
则 HTTPD 将当前目录设置为 /cgi-bin
(或 ScriptAlias 可能指向的任何位置),随后加载页面时,将期望 pic.gif
文件位于:/cgi-bin/pic.gif
,这通常不是预期的效果。
解决此问题的快速方法是使用绝对 URL。在上例中,如果图像标签为:
<IMG SRC="/~rasmus/pic.gif">
则不会出现问题。使用绝对 URL 并不总是理想的,因为它会降低页面的可移植性。此时您可能会有一个显而易见的问题,“为什么 PHP 不只是将当前目录更改到正确的位置?”。答案是 PHP 实际上确实会将当前目录更改为它正在显示的 HTML 文件的位置。在 PHP 脚本标签内使用的任何文件路径都可以是相对路径。问题是 PHP 无法控制的标签(例如 <img > 和 <a href >)不会通过 PHP 传递。解析这些标签时,PHP 将不再处于活动状态,并且当前工作目录已设置为 HTTP 守护程序指定的目录。
解决方案 是一个折衷方案。PHP 提供了一个名为 PATH_DIR 的变量。它始终包含当前 HTML 文件的目录部分。如果在 <img > 和 <a href > 标签中使用此 PATH_DIR 变量,则可以实现相对 URL 的效果,尽管在解析时,对服务器来说它看起来像是绝对 URL。从上面的例子来看,我们唯一需要做的更改是将 img 标签更改为:
<IMG SRC="<?echo $PATH_DIR>/pic.gif">通过使用上述方法,您可以移动包含此标签的文件,并且该标签将始终引用与源 HTML 文件位于同一目录中的
pic.gif
文件。另一种处理方法是在 HTML 文件中使用传统的 <BASE HREF=...>。
PHP 将检测来自 HTML 表单的 GET 和 POST 方法数据。需要理解的一点是,如果同时存在 GET 和 POST 方法数据,则始终首先处理 POST 方法数据。如果 PHP 变量由 POST 方法数据定义,或者如果变量由 Unix 环境中的 HTTP 守护程序定义,则 GET 方法数据无法覆盖它。这是为了防止有人向他们的 URL 添加 ?REMOTE_HOST=some.bogus.host,从而欺骗 PHP 日志记录机制记录此备用数据。但是,POST 方法数据允许覆盖这些变量。
GET 数据(URL 中“?”后的数据)的任何形式为 word=something 的组件都将定义变量 $word 以包含值 something。即使数据不是这种形式,也可以使用内置数组 $argv 访问它。例如,在这样的 URL 中:
/cgi-bin/php.cgi/[email protected]&var=valuePHP 符号表的相关组件将是:
$argc = 4 $argv[0] = abc $argv[1] = def $argv[2] = [email protected]&var=value $EMAIL_ADDR = [email protected] $var = value
请注意,数据的 EMAIL_ADDR 部分如何同时显示为未解析的 $argv[2],以及创建 $EMAIL_ADDR 变量以包含 [email protected]。
上面使用 $EMAIL_ADDR 变量作为示例,因为它是在使用 PHP 的日志记录功能时很有用的变量。通过添加:
?EMAIL_ADDR=
到用户电子邮件地址已知的页面的任何链接,您可以将其传播到下一页。PHP 日志系统将自动查找此变量,并将它的值记录为日志中的用户电子邮件地址。对于任何 PHP1 用户,以上内容与向用于在 PHP1 中执行此操作的 URL 添加 ?<!--$email--> 具有相同的功能。现在看起来稍微复杂一些,但它也完全通用,允许您构建自己的复杂页面。
在上例中,您还可以看到如何在GET方法数据中直接定义多个变量,方法是用“&”字符分隔每个变量。为了使这个用“&”分隔的变量列表有效,它必须是GET方法数据的最后一个(或唯一)组成部分。
HTML结构中的SELECT MULTIPLE标签允许用户从列表中选择多个项目。然后将这些项目传递给表单的动作处理程序。问题是它们都使用相同的窗口小部件名称传递。例如:
<SELECT NAME="var" MULTIPLE>
每个选定的选项都将以以下形式到达动作处理程序:
var=option1
var=option2
var=option3
每个选项都将覆盖前一个$var变量的内容。解决方法是使用PHP/FI的非索引数组功能。应使用以下方法:
<SELECT NAME="var[]" MULTIPLE>
这告诉PHP/FI将var视为一个数组,对var[]的每次赋值都会向数组中添加一个项目。第一个项目成为$var[0],下一个为$var[1],以此类推。count()函数可用于确定选择了多少个选项,如果需要,可以使用sort()函数对选项数组进行排序。
IMAGE SUBMIT
和PHP
提交表单时,可以使用图像代替标准提交按钮,方法如下:
<input type=image src=image.gif name=sub>
当用户点击图像上的某个位置时,相应的表单将连同两个附加变量sub_x和sub_y一起传输到服务器。它们包含用户在图像中点击的坐标。经验丰富的用户可能会注意到,浏览器发送的实际变量名包含句点而不是下划线,但PHP会自动将句点转换为下划线。
并非所有GD功能都受PHP支持。有关受支持函数的列表,请参见函数字母顺序列表。所有GD函数都以单词Image开头。
有关GD包的更多信息,请访问:http://www.boutell.com/gd/。
GD 1.2版权所有1994, 1995 Quest Protein Database Center, Cold Springs Harbor Labs。
PHP/FI将自动检测来自支持基于表单的文件上传功能的浏览器的文件上传,正如Xerox的E. Nebel和L. Masinter提出的并在RFC 1867中描述的那样。
可以通过创建一个类似于以下内容的特殊表单来构建文件上传屏幕:
<FORM ENCTYPE="multipart/form-data" ACTION="_URL_" METHOD=POST>
<INPUT TYPE="hidden" name="MAX_FILE_SIZE" value="1000">
Send this file: <INPUT NAME="userfile" TYPE="file">
<INPUT TYPE="submit" VALUE="Send File">
</FORM>
_URL_应指向php html文件。MAX_FILE_SIZE隐藏字段必须位于文件输入字段之前,其值为接受的最大文件大小。该值以字节为单位。在目标文件中,成功上传后将定义以下变量:
上传文件在服务器机器上存储的临时文件名。
发送方系统上文件的原始名称。
上传文件的字节大小。
如果浏览器提供了此信息,则为文件的MIME类型。例如,“image/gif”。
上述变量的$userfile基名将与上传表单中的NAME字段匹配。
默认情况下,文件将存储在服务器的默认临时目录中。可以通过在运行PHP/FI的环境中设置环境变量TMPDIR来更改此设置。但是,从PHP/FI脚本中使用PutEnv()调用来设置它将不起作用。或者,您可以通过编辑php.h并定义UPLOAD_TMPDIR变量来硬编码临时目录。
接收上传文件的PHP/FI脚本应实现确定应如何处理上传文件所需的任何逻辑。例如,您可以使用$file_size变量丢弃任何过小或过大的文件。您可以使用$file_type变量丢弃任何与特定类型条件不匹配的文件。无论逻辑如何,您都应该从临时目录中删除文件或将其移动到其他位置。
请注意,CERN httpd似乎会剥离从客户端获取的content-type MIME标头中从第一个空格开始的所有内容。只要这种情况存在,CERN httpd将不支持文件上传功能。
PHP/FI透明地支持Netscape规范中定义的HTTP Cookie。Cookie是用于在远程浏览器中存储数据,从而跟踪或识别回访用户的一种机制。您可以使用SetCookie()函数设置Cookie。Cookie是HTTP标头的一部分,因此必须在向浏览器发送任何输出之前调用SetCookie()函数。这与Header()函数的限制相同。
客户端发送给您的任何Cookie都将自动转换为PHP/FI变量,就像GET和POST方法数据一样。
如果您希望为单个Cookie分配多个值,只需在Cookie名称中添加[]即可。例如:
SetCookie("MyCookie[]","Rasmus Lerdorf", time()+3600);请注意,除非路径或域不同,否则Cookie将替换浏览器中相同名称的先前Cookie。因此,对于购物车应用程序,您可能需要保留一个计数器并将其传递。例如:
$Count++; SetCookie("Count",$Count, time()+3600); SetCookie("Cart[$Count]",$item, time()+3600);
mSQL代表mini-SQL,是由David Hughes编写的一个小型简单的SQL数据库引擎。它可以从ftp://ftp.bond.edu.au/pub/Minerva/msql获取。
PHP/FI支持丰富的mSQL支持函数集:
除了这些函数之外,PHP/FI还可以编译为自动转义在GET或POST数据中找到的任何前向单引号(')字符。如果在php.h文件中定义了MAGIC_QUOTES变量,则这些引号将自动转义,从而更容易将表单数据直接传递到msql查询中。
Postgres95/PostgreSQL是一个功能强大的公共领域数据库,它实现了SQL语言的一个重要子集。它支持许多在mSQL中不可用的数据类型和命令。有关Postgres和软件本身的更多信息,请访问此URL:http://www.postgreSQL.org/。
以下PHP函数可用于Postgres95:
注意:不支持二进制游标。
除了这些函数之外,PHP/FI还可以编译为自动转义在GET或POST数据中找到的任何前向单引号(')和双引号(")字符。如果在php.h文件中定义了MAGIC_QUOTES变量,则这些引号将自动转义,从而更容易将表单数据直接传递到Postgres查询中。
这是一个示例脚本,它连接到名为“mydb”的本地主机上的Postgres数据库,并检索表中人员的姓名和年龄:
<? $conn = pg_Connect("localhost", "5432", "", "", "mydb"); if (!$conn) { echo "An error occured.\n"; exit; } $result = pg_Exec($conn, "select * from table1"); if (!$result) { echo "An error occured.\n"; exit; } $num = pg_NumRows($result); $i = 0; while ($i < $num) { echo "name: "; echo pg_Result($result, $i, "name"); echo " age: "; echo pg_Result($result, $i, "age"); echo "<BR>"; $i++; } pg_FreeResult($result); pg_Close($conn); >
mysql是mSQL包的克隆。您可以从http://www.tcx.se/获取副本。
PHP/FI支持丰富的mysql支持函数集:
除了这些函数之外,PHP/FI还可以编译为自动转义在GET或POST数据中找到的任何前向单引号(')字符。如果在php.h文件中定义了MAGIC_QUOTES变量,则这些引号将自动转义,从而更容易将表单数据直接传递到mysql查询中。
Solid服务器是一个高容量SQL服务器。它支持ANSI SQL2、ODBC、SAG CLI和X/Open SQL标准。有关Solid服务器的更多信息,请访问www.solidtech.com。PHP的Solid接口由DigiFace Internet Services开发。
以下PHP函数可用于Solid Server:
除了这些函数之外,PHP/FI还可以编译为自动转义在GET或POST数据中找到的任何前向单引号(')字符。如果在php.h文件中定义了MAGIC_QUOTES变量,则这些引号将自动转义,从而更容易将表单数据直接传递到Solid查询中。
这是Postgres部分中显示的相同脚本,已针对Solid服务器进行了调整。
<? $conn = Solid_Connect("", "username", "password"); if (!$conn) { echo "An error occured.\n"; exit; } $result = Solid_Exec($conn, "select * from table1"); if (!$result) { echo "An error occured.\n"; exit; } while (Solid_FetchRow($result)) { echo "name: "; echo Solid_Result($result, "name"); echo " age: "; echo Solid_Result($result, "age"); echo "<BR>"; } Solid_FreeResult($result); Solid_Close($conn); >
以下PHP/FI函数可用于Sybase。
有关完整的示例,请参见sybSQL_Result()函数后面的示例。
以下PHP/FI函数可用于Oracle:
一个示例PHP/FI Oracle应用程序:
<? PutEnv("ORACLE_HOME=path_to_your_oracle_home" PutEnv("ORACLE_SID=database" /* Establish a connection between PHP and Oracle. */ $conn = Ora_Logon("username" "password" if ($conn < 0) { echo("Could not connect to Oracle.\n" exit; } /* Open a cursor in Oracle. */ $cursor = Ora_Open($conn); if ($cursor < 0) { echo("Could not open a cursor.\n" Ora_Logoff($conn); exit; } /* Turn off autocommit. */ Ora_CommitOff($conn); /* This is the SQL query. */ $query = "SELECT * FROM some_table" if (Ora_Parse($cursor, $query) < 0) { echo("Parse failed!\n" Ora_Logoff($conn); exit; } /* Execute the SQL statement associated with $cursor and prepare storage for select-list items. */ $ncols = Ora_Exec($cursor); echo "lt;P>\n" echo "lt;TABLE BORDER=1 CELLSPACING=0>\n" /* Retrieve all rows from the database one after another. */ while (Ora_Fetch($cursor) == 1) { $i = 0; echo "lt;TR>\n" while ($i < $ncols) { /* Get data for a single column of currently fetched row. */ $col = Ora_GetColumn($cursor, $i); echo("lt;TD>$col</TD>\n" $i++; } echo("lt;/TR>\n" } echo "</TABLE>\n"; /* Close the Oracle connection. */ Ora_Close($cursor); /* Disconnect the logon data area. */ Ora_Logoff($conn); >
Illustra是由Informix销售的商业数据库。它的一些功能尚未完全受此接口支持。Illustra的主要优势在于它是一个对象关系数据库,能够以面向对象的方式进行扩展。例如,可以在数据库中使用图像作为基类型。更多信息可以从Illustra主页获取。
以下PHP函数可用于Illustra:
注意:目前尚不支持类型操作。
这是一个示例脚本,它连接到名为“mydb”的本地 illustra 数据库并检索表中人员的姓名和年龄
<? $conn = mi_Connect("mydb", "username", "password"); if ($conn<0) { echo "An error occured on connection.\n"; exit; } $result = mi_Exec($conn, "select * from table1"); if ($result < 0) { echo "An error occured.\n"; exit; } $num = mi_NumRows($result); $i = 0; while ($i < $num) { echo "name: "; echo mi_Result($result, $i, "name"); echo " age: "; echo mi_Result($result, $i, "age"); echo "<BR>"; $i++; } mi_Close($conn); >
Adabas D 是一款高级 RDBMS,可在许多平台上使用。一个特殊的版本,所谓的个人版,可免费用于 Linux 和 Win32。它限制为 5 个同时用户和 100 MB 的数据。有关 Adabas D 的更多信息,请参阅 http://www.softwareag.com。
以下 PHP 函数可用于访问 Adabas 数据库
<? $conn = Ada_Connect("node:db", "username", "password"); if (!$conn) { echo "An error occured.\n"; exit; } $result = Ada_Exec($conn, "select * from table1"); if (!$result) { echo "An error occured.\n"; exit; } while (Ada_FetchRow($result)) { echo "name: "; echo Ada_Result($result, "name"); echo " age: "; echo Ada_Result($result, "age"); echo "<BR>"; } Ada_FreeResult($result); Ada_Close($conn); >
正则表达式用于 PHP/FI 中的复杂字符串操作。正则表达式支持的脚本接口是通过以下函数:EReg()、ERegi()、EReg_Replace()、ERegi_Replace()、Reg_Match()、Reg_Replace() 和 Reg_Search()。所有三个函数的第一个参数都是正则表达式字符串。EReg 函数使用 POSIX 1003.2 定义的 POSIX 扩展正则表达式,而 Reg 函数实现基本正则表达式。有关正则表达式的完整说明,请参阅您的 regex(7) 手册页。如果您没有此页面,则可以在 PHP/FI 发行版的 src/regex 目录中找到 Henry Spencer 编写的 regex(7) 手册页。请您的系统管理员为您安装此手册页。
一些正则表达式的示例及其作用
ereg("abc",$string);
- 如果在 $string 中的任何位置找到“abc”,则返回 true。
ereg("^abc",$string);
- 如果在 $string 的开头找到“abc”,则返回 true。
ereg("abc$",$string);
- 如果在 $string 的结尾找到“abc”,则返回 true。
eregi("(ozilla.[23]|MSIE.3)",$HTTP_USER_AGENT);
- 如果客户端浏览器是 Netscape 2、3 或 MSIE 3,则返回 true。
ereg("([[:alnum:]]+) ([[:alnum:]]+) ([[:alnum:]]+)",$string,$regs);
- 将三个用空格分隔的单词放入 $regs[1]、$regs[2] 和 $regs[3] 中。
ereg_replace("^","<BR>",$string)
- 在 $string 的开头添加 <BR> 标记。
ereg_replace("$","<BR>",$string)
- 在 $string 的结尾添加 <BR> 标记。
ereg_replace(10,"",$string);
- 去除 $string 中的任何换行符。
ereg_replace(13,"<BR>",$string);
- 将 $string 中的所有回车符替换为 <BR> 标记。
在大多数使用带引号的字符串参数的地方都支持以下转义序列
\a --> bell \b --> backspace \n --> linefeed \r --> carriage return \t --> tab \nnn --> octal char \xXX --> hex char
PHP/FI 脚本语言中的一些函数期望使用八进制参数来表示 Unix 风格的权限参数。在此八进制表示法中,使用 3 位来表示值 0-7。这三位的每一位都表示特定的权限。八进制传统上在某些上下文中用前导 0 表示,例如 0755。您无需在 PHP 中使用此前导 0,因为期望八进制参数的函数只会简单地假设参数为八进制。但是,使用前导 0 是一种良好的实践,可以提醒您不再处理基数为 10 的值。
位 描述
xxx ^^^ ||+----1 bit (execute permission) |+-----2 bit (write permission) +------4 bit (read permission)这三位重复三次,分别用于所有者、组和世界。因此,0755 表示
owner: r,w,x group: r, ,x world: r, ,x请注意,目录上的执行位表示“访问”,而不是“执行”。第四个八进制 nibble 中还有扩展位,例如 0?755
4: suid bit (set userid) 2: sgid bit (set group id) 1: sticky bit (on a directory, only the owner can delete a file)
PHP 脚本语言在许多方面与 C 语言的语法类似。它支持变量、数组、函数调用、不同的变量类型以及编写复杂 cgi 程序所需的大多数内容。
以下部分描述了每个 PHP/FI 函数,只需将 #function_name 附加到此文档的 url 即可快速找到它们,因为每个函数描述都已用其名称进行了标记。
每个 PHP 指令以<?开头,以>结尾。或者,指令可以分组在一个<? >对中,并用;字符分隔。
支持变量,并通过在变量名前添加$来表示。例如,要将变量设置为 5,然后显示此变量,以下内容是有效的
<?$a = 5> <?echo $a>
这与编写以下内容相同
<? $a = 5; echo $a >
甚至
<? $a = 5; echo $a; >
额外的空格字符(如空格、制表符和换行符)将被忽略。此事实应用于格式化 PHP 脚本块,以使其更易于阅读。变量名称区分大小写,但函数调用不区分大小写。在本文档后面的函数概述中,大小写仅用于使函数名称更易于阅读。在实际的脚本语言中,您可以使用任何您想要的大小写。
支持注释。注释的编写方式与 C 语言中的注释相同。/* 开始注释,*/ 结束注释。注释可以放置在<? ... >块中的任何位置。
支持三种类型的变量。长整数、双精度浮点数和字符字符串。它们会自动检测。例如
<?$a = 5>
导致 $a 成为 INTEGER 类型的变量。
<?$a = 5.0>
导致 $a 成为 DOUBLE 类型的变量。
<?$a = "5">
导致 $a 成为 STRING 类型的变量。
变量的类型通常并不重要。每个变量,无论其类型如何,都会在内部转换为所有三种类型,并且各种函数都会尝试使用正确的类型。只有少数几个函数受变量类型的影响。
所有三种变量类型也可以通过在其名称后附加[value]来作为数组处理。与 C 不同,这些实际上是类似于 Perl 中使用的关联数组。以下将有效
<? $a[0] = 5; $a["hello"] = 6; echo $a[0]; echo $a["hello"]; >
请注意,如果变量同时用作数组和普通变量,则普通变量与数组中的索引“0”条目同义,即
$a = 1;
这与编写以下内容相同
$a[0] = 1;
PHP/FI 也支持非索引数组。非索引数组会在向其中添加项目时生成自己的索引。例如
$a[] = "Hello"; $a[] = "There";
插入到非索引数组中的第一项始终分配索引 0,第二项分配索引 1,依此类推。因此,可以使用以下命令打印出上述项目
echo $a[0]; echo $a[1];
可以通过简单的赋值来复制数组。如果 $b 是一个数组,则可以使用以下命令将所有值复制到名为 $a 的新数组中
$a = $b;
请注意,如果 PHP 不强制您在使用变量之前定义它们。如果在上一个语句中,$b 未定义,则 $a 将设置为空字符串 ("")。
[] 表示法也用于指示要追加数组。如果 $a 和 $b 都是数组,则可以使用以下命令将 $b 追加到 $a
$a[] = $b;
在上面,关联数组和普通编号数组之间会有所不同。编号数组将被重新编号,以便 $b 中的所有元素都位于 $a 中的原始元素之后。而对于关联数组,$b 中的元素将与 $a 中的元素合并。$a 中已存在的任何元素(具有相同索引名称的项目)都将被 $b 元素覆盖。
您可以使用 count() 函数来确定任何数组中的项目数量。
语言本身也固有地决定了变量的类型如何确定某些基本操作的执行方式。例如
$a = $b + $c;
可以执行几件事。如果 $b 是一个数字,则将 $c 的数值添加到 $b 中,并将总和存储在 $a 中。在这种情况下,$c 的类型无关紧要。操作由第一个变量的类型引导。如果 $b 是一个字符串,则将 $c 的字符串值附加到 $b 中,并将结果字符串放入 $a 中。这也导致一些注意事项。您应该阅读关于 重载运算符 的部分,以更好地了解如何处理它们。
上一节介绍了关联数组。关联数组是一个数组,其中索引不必是数值顺序值。数组索引可以是任何数字或字符串。PHP/FI 提供了一组函数来操作这些关联数组。这些包括 Next()、Prev()、Reset()、End() 和 Key()。
有时,能够拥有可变变量名很方便。也就是说,可以动态设置和使用的变量名。普通变量使用以下语句设置
$a = "hello";
可变变量采用变量的值,并将其视为变量的名称。在上面的示例中,hello 可以通过使用两个美元符号来用作变量的名称,即
$$a = "world";
此时,两个变量已定义并存储在 PHP/FI 符号树中
Variable Name Variable Content a hello hello world
因此,此语句
echo "$a $$a";
产生的输出与以下内容完全相同
echo "$a $hello";
即它们都产生:hello world
就语言结构而言,PHP 语言非常简单。以下命令用于引导文件中的控制流
条件的语法类似于 C 语言。== 测试相等性。!= 表示不相等。还支持:>、<、>=、<=。条件 AND 是&&,条件 OR 是||。
示例
<? if($a==5 && $b!=0 ); $c = 100 + $a / $b; endif; >
以上内容也可以用标准 C 语法编写
在这种情况下,不需要在闭合大括号后添加分号。
<? if($a==5 && $b!=0) { $c = 100 + $a / $b; } >
这两种语法之间没有区别。我个人喜欢使用 endif、endswitch 和 endwhile,这样我明确知道我正在结束哪个结构。但是,这些结束结构始终可以用闭合大括号替换。
需要注意的是,语言的流程并不依赖于代码中脚本块的组织方式。你可以在一个块中开始一个if表达式,并在另一个块中结束该表达式。例如
<?if($a==5 && $b!=0)> <b>Normal html text</b> <?endif>
在这个例子中,很容易看出为什么有时更希望使用endif
关键字而不是闭合大括号。上面的代码比下面的代码更易读
<?if($a==5 && $b!=0) {> <b>Normal html text</b> <? } >
这两个版本都是有效的,它们会做完全相同的事情。
你可以使用以下语法在PHP脚本中定义一个函数
<? Function Test ( echo "This is a test\n"; ); >
只要调用在函数定义之后,就可以从脚本中的任何位置调用此函数。一个示例调用可能是
<? Test(); >
像这样的用户定义函数的行为与PHP的内部函数完全相同,你可以向它们传递参数并让它们返回值。这是一个接受3个参数并返回这些参数之和的函数定义语法
<? Function Sum $a,$b,$c ( return($a+$b+$c); ); echo Sum($a,$b,$c); >
return语句用于从函数返回值。使用这种机制只能返回单个值,但是,如果需要在主代码和函数之间来回传递更多值,可以使用全局变量。这将我们引到变量作用域的部分。
变量的作用域是定义它的上下文。在大多数情况下,所有PHP/FI变量只有一个作用域。但是,在用户定义的函数中,引入了局部函数作用域。在函数内部使用的任何变量默认情况下都仅限于局部函数作用域。例如
$a=1; /* global scope */ Function Test ( echo $a; /* reference to local scope variable */ ); Test();
这段脚本不会产生任何输出,因为echo语句引用的是$a变量的局部版本,并且在这个作用域内没有为它赋值。你可能会注意到,这与C语言略有不同,因为C语言中的全局变量会自动提供给函数,除非被局部定义专门覆盖。这可能会导致一些问题,因为人们可能会无意中更改全局变量。在PHP/FI中,如果要在函数中使用全局变量,必须在函数内部声明为全局变量。一个例子
$a=1; $b=2; Function Sum $first,$second ( global $a,$b; $b = $a + $b; ); Sum(); echo $b;
上面的脚本将输出“3”。通过在函数内部声明$a和$b为全局变量,对这两个变量的所有引用都将指向全局版本。函数可以操作的全局变量数量没有限制。但是,变量必须在调用函数之前存在于全局作用域中。你不能在函数内部创建新的全局变量。
变量作用域的另一个重要特性是static变量。静态变量只存在于局部函数作用域中,但在程序执行离开该作用域时不会丢失其值。考虑以下示例
Function Test ( $a=0; echo $a; $a++; );
这个函数相当无用,因为每次调用它时,它都会将$a设置为0并打印“0”。$a++递增变量毫无意义,因为一旦函数退出,$a变量就会消失。为了创建一个不会丢失当前计数的有用计数函数,$a变量被声明为静态变量
Function Test ( static $a=0; echo $a; $a++; );
现在,每次调用Test()函数时,它都会打印$a的值并递增它。
当函数递归调用时,静态变量也是必不可少的。递归函数是调用自身的函数。编写递归函数时必须小心,因为有可能使其无限递归。你必须确保有足够的方法来终止递归。以下简单函数递归地计数到10
Function Test ( static $count=0; $count++; echo $count; if($count < 10) { Test(); } );
PHP支持在任何期望表达式的任何地方进行完整的数学运算。运算顺序会被考虑在内。以下是有效的运算符
<? $a = 2 + 1 > Addition <? $a = 2 - 1 > Subtraction <? $a = 2 * 1 > Multiplication <? $a = 2 / 1 > Division <? $a = 2 % 1 > Modulus <? $a = 2 ^ 1 > Bit-wise Exclusive OR
支持括号和运算顺序,因此以下是有效的
<?$a = (2+1)*3+6/3>
支持类似C语言的自增运算符+=
和-=
。例如
<? $a += $b>
这相当于
<? $a = $a + $b>
支持类似C语言的按位运算符&=
、|=
和^=
。例如
<? $a &= 4>这相当于
<? $a = $a & 4>
你可以使用while(); endwhile;结构在PHP脚本中循环。
<? $a=0; while($a<100) { $a++; echo $list[$a]; } >
上面的例子展示了使用while循环显示数组内容。**警告** 虽然PHP语言支持诸如++和--之类的增量运算符来递增和递减变量,但它们并不像在C语言中那样被完全处理。变量会立即递增。不像C语言那样,没有在操作之前或之后递增变量的概念。
如上文语言结构部分所述,可以使用while(); endwhile;获得相同的结果。
PHP支持一个与C语言等效的switch结构。
<? $a=0; switch($a) { case 1; echo "a is 1"; break; case "hello"; echo "a is hello"; break; default; echo "a is unknown"; break; } >
以上是一个switch结构的例子。它类似于一系列if/elseif/else结构,但更易于阅读。PHP switch结构与C语言的唯一区别在于使用分号来终止每一行。没有冒号。
如上文语言结构部分所述,可以使用switch(); endswitch;获得相同的结果。
所有这些结构当然可以像C语言一样嵌套和相互使用。PHP发行版的examples目录中的各种文件应该为学习该语言提供一个良好的起点。
前面一部分讨论了GET和POST方法数据和变量。如果你仔细考虑一下,你可能会想到一个安全问题。例如,如果在一个网页上,我从数据库中获取了一些数据,并通过POST方法表单中的名为“data”的变量传递这些数据。在接下来的页面中,我可以访问这个变量并对其进行处理。但是,如果有人直接访问第二个页面并在URL中添加“?data=something”,从而进行GET方法变量设置,他们就有效地绕过了原始的POST方法表单。
PHP提供了一个SecureVar()函数,用于将变量名标记为安全变量。这些安全变量只能直接在PHP脚本中设置,或者来自POST方法表单。它们不能使用GET方法变量定义机制进行设置。从我们上面的场景来看,如果我们在第二页的开头附近放置一行
<?SecureVar("data")>
那么GET方法技巧将不起作用。“data”变量将显示为空,除非它直接来自第一页的POST方法表单。
SecureVar()实际上接受正则表达式作为参数,因此你可以标记应该以这种安全方式处理的变量名模式。例如,
<?SecureVar(".*data.*")>
将标记任何名称中包含“data”一词的变量为安全变量。
请注意,POST方法表单本身并不安全。人们可以通过简单地telnet到系统上的HTTP端口来模拟向表单发布任何数据。如果安全确实是一个问题,你需要采取适当的安全措施来阻止人们这样做。
问题是PHP理解3种变量类型:整数、双精度浮点数和字符串。当第一次赋值变量时,PHP会自动确定变量类型。
例如
$a = 1; Type would be integer $b = 1.5; Type would be double $c = "1"; Type would be string
现在,当你做类似的事情时会发生什么
$d = $a + $c;
解析器查看算术表达式的第一部分,并用它来确定结果的类型,从而也确定要执行的算术运算的性质。在上述情况下,由于$a是整数,$d将是整数,并且执行整数加法,结果为
$d = 2 Type is integer
因此
$d = $c + $a
结果为
$d = "11" Type is string
以上对我来说是有意义的,一旦你理解了它,它可能就可行了。但是,当使用更复杂的表达式时,它可能会变得极其混乱。
解决方案是一个简单的类型转换机制。实际上,所有变量都会自动转换为所有三种类型,并且内部标志只是标记变量的实际类型。因此,当我这样说时
$a = 1;
在符号表中内部存储3个版本。
Integer: 1 <-- flag Double : 1.0 String : "1"
SetType()函数可以移动指示变量类型的标志。
SetType($a,"double");
这将强制从那时起将$a视为双精度浮点数。
GetType()函数返回类型。GetType($a)
在这种情况下将返回“double”。
还存在函数可以返回三种不同类型而不会移动类型标志。
IntVal($a) returns 1 DoubleVal($a) returns 1.0 StrVal($a) returns "1"
这不会改变PHP变量的重载运算符特性,但它确实为你提供了一些更好地处理它们的工具。PHP并非一个完整的Perl仿制品。它必须小而快。Perl通过强制“+”运算符仅对数字起作用来处理重载运算符的陷阱。如果你想添加字符串,你必须使用“.”运算符。一旦你开始为每种类型使用单独的运算符,你就会开始使语言变得更加复杂。例如,你不能对字符串使用'==',现在你将使用'eq'。我不明白这样做有什么意义,特别是对于像PHP这样的东西,大多数脚本都相当简单,并且在大多数情况下是由非程序员编写的,他们想要一种具有基本逻辑语法并且学习曲线不高简单的语言。
在某些情况下,可能需要忽略特定PHP函数可能报告的致命错误。例如,你可能想要忽略dbmopen()调用的错误,只需检查调用的返回值,而无需在网页屏幕上显示错误消息。这可以通过在函数调用前面加上“@”字符来实现。例如
$err_code = @dbmopen($filename,"w");
可以通过查看PHP内部变量$phperrmsg来检查本来会打印的实际错误消息。
抑制错误消息打印的更通用的方法是使用SetErrorReporting()函数。使用此函数,可以通过在代码块前面加上类似的调用来禁用整个代码块的错误打印
SetErrorReporting(0);
这将关闭所有错误。然后可以使用以下方法重新启用它们
SetErrorReporting(1);
PHP有很多内置函数。函数的调用方式与C语言中的调用方式相同。有些函数接受一个或多个参数,有些函数返回值,然后可以将这些返回值赋给变量或用作另一个函数的参数。例如
<?$t=time()>
这将time()函数的返回值赋给t变量。
Abs返回arg的绝对值。
Ada_Close将关闭与给定连接标识符关联的Adabas服务器的连接。
只有在PHP中启用了Adabas支持后,此函数才可用。
Ada_Connect打开与Adabas服务器的连接。每个参数都应该是一个带引号的字符串。第一个参数(数据源名称)是一个“servername:databasename”形式的字符串。如果你想访问本地数据库,可以省略服务器名(但不包括冒号)。此函数返回一个connection_id。其他Adabas函数需要此标识符。你可以同时打开多个连接。此函数在出错时将返回0。
只有在PHP中启用了Adabas支持后,此函数才可用。
Ada_Exec将SQL语句发送到connection_id指定的Adabas服务器。connection_id必须是由Ada_Connect返回的有效标识符或特殊值0。如果connection_id为0,ada_exec将尝试使用配置指令phpAdaDefDB, phpAdaUser和phpAdaPW给出的参数建立或使用连接。
此函数的返回值是一个标识符,用于通过其他 Adabas 函数访问结果。如果发生错误,此函数将返回 **0**。如果命令执行正确但预期不返回数据(例如插入或更新命令),则将返回 **1**。请注意,不返回数据的查询仍将返回大于 1 的有效结果。
只有在PHP中启用了Adabas支持后,此函数才可用。
Ada_FetchRow 获取由 Ada_Exec 返回的数据的一行。调用 Ada_FetchRow 后,可以使用 Ada_Result 访问该行的字段。如果没有给出行号,Ada_FetchRow 将尝试获取结果集中的下一行。每次调用 Ada_FetchRow 时,都可以通过 Ada_Result 访问新的一行。如果 Ada_FetchRow 成功(存在一行),则返回 **1**;如果没有更多行,Ada_FetchRow 将返回 **0**。Ada_FetchRow 的返回值可以用作 while 循环的条件。可以混合使用带行号和不带行号的 Ada_FetchRow() 调用。要多次遍历结果,可以使用行号 1 调用 Ada_FetchRow(),然后继续使用不带行号的 Ada_FetchRow() 来查看结果。
只有在PHP中启用了Adabas支持后,此函数才可用。
Ada_FieldName 将返回在给定的 Adabas 结果标识符中占据给定列号的字段名称。字段编号从 0 开始。
只有在PHP中启用了Adabas支持后,此函数才可用。
Ada_FieldNum 将返回在给定的 Adabas 结果标识符中对应于命名字段的列槽号。字段编号从 0 开始。此函数在发生错误时将返回 **-1**。
只有在PHP中启用了Adabas支持后,此函数才可用。
Ada_FieldType 将返回在给定的 Adabas 结果标识符中按名称或编号引用的字段的 SQL 类型。注意:字段编号从 0 开始。
只有在PHP中启用了Adabas支持后,此函数才可用。
只有在担心脚本运行时使用过多内存时,才需要调用 Ada_FreeResult。脚本完成后,所有结果内存都将自动释放。但是,如果您确定在脚本中不再需要结果数据,则可以将结果标识符作为参数调用 Ada_FreeResult,并且相关的结果内存将被释放。
只有在PHP中启用了Adabas支持后,此函数才可用。
Ada_NumFields 将返回 Adabas 结果中的字段(列)数。参数是由 Ada_Exec 返回的有效结果标识符。此函数在发生错误时将返回 **-1**。
只有在PHP中启用了Adabas支持后,此函数才可用。
Ada_NumRows 将返回 Adabas 结果中的行数。参数是由 Ada_Exec 返回的有效结果标识符。此函数在发生错误时将返回 **-1**。对于 INSERT、UPDATE、DELETE 语句,Ada_NumRows() 返回受影响的行数。对于 SELECT 子句,这是可用行数。
只有在PHP中启用了Adabas支持后,此函数才可用。
Ada_Result 将返回 Ada_Exec 生成的结果标识符中的值。字段名称指定要返回的行中的哪个单元格。您可以使用字段索引作为未加引号的数字来代替命名字段。字段索引从 0 开始。如果请求的字段是 BYTE(二进制)代码类型或长度超过 4096 字节,则内容将直接发送到客户端。提示:[VAR]CHAR BYTE 字段可以使用 HEX() 数据库函数返回到 php 变量中;例如 SELECT HEX(SYSKEY) SYSKEY FROM MYTABLE。
只有在PHP中启用了Adabas支持后,此函数才可用。
Ada_ResultAll 将打印 Ada_Exec 生成的结果标识符中的所有行。结果以 HTML 表格格式打印。使用可选的 format 字符串可以进行额外的整体表格格式设置(例如,bgcolor= 将设置背景颜色,>caption> </caption 设置标题)。注意:“format”的内容将像这样插入到 HTML 表格标签中 <table format >…
只有在PHP中启用了Adabas支持后,此函数才可用。
使用反斜杠转义任何 $ \ 或 '(如果设置了 MAGIC_QUOTES)。另请参见 StripSlashes()。
Sort 用于按升序对 PHP 关联数组进行排序。使用 ARSort() 进行降序排序。与 Sort() 函数不同,ASort() 保持索引值配对。它理解三种变量类型,如果数组包含字符串,则按字母顺序排序;如果数组包含数字,则按数字顺序排序。对于包含混合类型的数组,数组中的第一种类型将指定排序方法。请注意,如果要排序非关联数组,则应使用 Sort() 函数。
BinDec 返回由 binary_string 参数表示的二进制数的十进制等效值。可以转换的最大数字是 31 位长,即十进制的 4294967295。另请参见 DecBin() 函数。
Ceil() 将浮点值向上舍入到下一个整数。返回值为 double 类型(浮点型),以便可以正确地用于复杂的方程式。要获得整数类型,请使用:$new = IntVal(Ceil($value));
另请参见 Floor()。
ChDir 将当前工作目录更改为参数中指定的目录。
ChGrp 更改指定文件的组 ID。
ChMod 更改指定文件的权限。perms 参数必须以 八进制 表示法指定。例如 ChMod($filename,0755)
ChOwn 将指定文件更改为由指定所有者拥有。请注意,只有当 PHP/FI 二进制文件以 root 身份运行时(这通常不是一个好主意),此方法才有效。
Chop 删除所有尾随空格,包括换行符、制表符和空格,并返回新的字符串。
Chr 返回由整数参数表示的 ASCII 字符。
ClearStack() 函数是针对 PHP 解析器中的缺陷的一种解决方法。这个缺陷是 PHP 只拥有一个表达式堆栈。在用户定义的函数内部,这个表达式堆栈永远不会被清除,因为它的内容可能在调用用户定义函数的上下文中复杂的表达式中需要。这意味着,如果您在一个用户定义的函数内有一个有很多迭代的 while 循环,您可能会消耗大量的堆栈空间。您甚至可能会达到最大数据空间限制。您可以在 while 循环中添加对 ClearStack() 的调用来防止这种内存消耗,但权衡是您不能在任何上下文中使用您的函数。即,您必须将函数的输出赋值给一个临时变量,然后在您需要的任何上下文中使用这个临时变量。
在大多数操作系统上,stat() 系统调用通常是一个昂贵的操作。为了确保对各种 File* 函数(如 FilePerms()、FileInode() 等)的重复调用,上次 stat() 调用的结果始终被缓存。如果其中一个 File* 函数再次使用相同的参数调用,则将使用缓存的 stat() 结果。为了强制进行新的 stat() 系统调用,可以调用此 ClearStatCache() 函数来清除缓存的 stat() 结果。
closeDir 关闭使用 openDir 函数打开的目录。
CloseLog() 关闭 Syslog() 用于写入系统日志记录程序的描述符。有关更多详细信息,请参见 closelog(3) UNIX 手册页。另请参见 Syslog()、OpenLog() 和 InitSyslog()。
Count 返回数组变量中的项目数。如果变量不是数组,则返回值将为 1(因为普通变量类似于只有一个项目的数组)。如果变量未定义,则返回值将为 0。
Crypt 将使用标准 Unix DES 加密方法加密字符串。参数是要加密的字符串和一个可选的两个字符的盐字符串,用于作为加密的基础。有关更多信息,请参见 Unix 系统的 crypt 函数的手册页。如果您的 Unix 系统上没有 crypt 函数,您可以使用 Michael Glad 在丹麦开发的公共领域 UFC-Crypt 包,只要您从非美国站点通过 ftp 获取它,就不受美国出口法的限制。
Date 函数用于以各种方式显示时间和日期。该函数采用格式字符串和时间作为参数。如果省略时间参数,则将使用当前时间和日期。时间参数指定为自 Unix 纪元 1970 年 1 月 1 日以来的秒数的整数。格式字符串用于指示应显示哪些日期/时间组件以及如何对其进行格式化。格式字符串中识别以下字符。任何无法识别的字符都将详细打印。
Y - 年份,例如 1995
y - 年份,例如 95
M - 月份,例如 Oct
m - 月份,例如 10
F - 月份,例如 October
D - 星期几,例如 Fri
l - 星期几,例如 Friday
d - 日,例如 27
z - 一年中的第几天,例如 299
H - 24 小时制的小时,例如 13
h - 12 小时制的小时,例如 1
i - 分钟,例如 5
s - 秒,例如 40
U - 自纪元以来的秒数,例如 814807830
A - AM/PM
a - am/pm
另请参见 MkTime() 函数。
dbList 输出有关编译到 PHP 中的数据库支持的信息。
dbmClose 只关闭指定的 dbm 文件。它还将解锁任何锁文件,因此关闭任何已打开的 dbm 文件非常重要。
dbmDelete 将删除由给定 key 参数指定的键/内容对。
如果键存在,dbmExists 将返回 1,否则返回 0。
dbmFetch 将返回与给定键关联的内容字符串。
dbmFirstKey 返回 dbm 文件中的第一个键。请注意,不保证任何特定顺序,因为顺序取决于在 dbm 实现中计算的哈希表值。如有必要,您可以使用 Sort 函数对来自 dbm 文件的数据数组进行排序。
dbmInsert 将新的键/内容数据对插入到 dbm 文件中。如果键已存在,则插入将失败。
dbmNextKey 返回指定键后的下一个键。通过调用 **dbmfirstkey()** 然后连续调用 **dbmnextkey()**,可以访问 dbm 文件中的每个键/内容对。
dbmOpen() 打开一个 dbm 文件。第一个参数是要打开的 dbm 文件的完整路径文件名,第二个是文件打开模式,可以是 **"r"**、**"n"** 或 **"w"**,分别表示读取、新建(表示写入)和写入。如果使用 ndbm 支持,ndbm 实际上将创建 *filename.dir* 和 *filename.pag* 文件。gdbm 只使用一个文件,内部平面 ascii 文件支持也是如此,而 Berkeley 的 libdb 创建一个 *filename.db* 文件。请注意,PHP 除 dbm 库本身可能执行的任何文件锁定外,还执行自己的文件锁定。PHP 不会删除它创建的 *.lck* 文件。它仅将这些文件用作其上进行文件锁定的固定 inode。有关 dbm 文件的更多信息,请参见您的 Unix 手册页,或从 ftp://prep.ai.mit.edu/pub/gnu 获取 GNU 的 gdbm。
dbmReplace 类似于 **dbminsert()** 函数,唯一的区别在于,如果键已存在,则旧内容字符串将被新内容字符串替换。
DecBin 函数返回一个字符串,其中包含给定数字参数的二进制表示。可转换的最大数字长度为 31 位,或十进制的 4294967295。另请参见 BinDec() 函数。
DecHex 函数将十进制数字转换为十六进制字符串。另请参见 HexDec() 函数。
DecOct 函数将十进制数字转换为八进制数字。另请参见 OctDec()。
Echo 不是函数,即,不要在它的参数周围加上括号。它用于显示 PHP 函数或 PHP 变量的结果。有关支持的特殊字符列表,请参见 转义字符部分。format_string 是可选的,如果不存在,则不会进行任何输出格式化。格式字符串类似于 C printf 函数的格式字符串。有关更多详细信息,请参见 printf 的手册页。单个 echo 命令最多可以打印 5 个表达式。如果尝试打印更多内容,则会收到解析器错误。请注意,表达式的类型无关紧要。如果存在格式字符串,则表达式会自动转换为格式字符串指定的适当类型。如果要格式化某些内容并将格式化后的字符串分配给变量而不是显示它,请使用 sprintf() 函数。
支持以下转换:
- %d %i
- 打印带符号的十进制数。
- %o
- 打印八进制数。
- %u
- 打印无符号十进制数。
- %x %X
- 打印十六进制数。
- %f
- 打印浮点数。
- %e %E
- 以科学计数法打印浮点数。
- %g %G
- 根据需要以科学计数法或普通计数法打印浮点数。
- %c
- 打印单个字符。
- %s
- 打印字符串。
- %%
- 打印字面百分号。
接受以下标志:
- '-'
- 左对齐输出,在字段宽度内。
- '+'
- 确保所有整数都有符号(带正/负号)。
- ' '
- 类似于“+”,但使用空格而不是加号。
- '#'
- 在十六进制和八进制数前面打印前缀,以将其标识为十六进制和八进制数。
- '''
- 将数字分成组(通常是三个数字一组的逗号分隔组)。
- '0'
- 用零填充字段宽度。
所有这些标志都取决于 C 库的 printf 函数是否支持它们(例如“,”是 GNU 扩展)。
大多数转换都接受字段宽度和精度,如 /examples 目录中的
demo_echo.html
文件所示。不必指定任何类型修饰符,实际上,如果类型修饰符没有意义(几乎总是这样),PHP 会报错。PHP 会抱怨(并拒绝接受)任何它无法识别的东西。给出的任何额外参数(格式字符串不需要)都会被忽略。
End 函数将给定变量的内部数组指针移动到数组的最后一项,并返回该项的值。这对于反向遍历关联数组很有用。另请参见 Reset() 和 Prev()。以下示例将反向遍历关联数组
<? Reset($array); $first_key = key($array); End($array); $k = key($array); while($k != $first_key); echo $array[$k]; prev($array); $k = key($array); endwhile; echo $array[$k]; >
如果在参数字符串中匹配正则表达式,则 ereg 函数返回非零值。例如,条件 <?if (ereg("^This.*", "This is an example string")>
将为真,因为 "^This.*" 表达式表示匹配字符串开头的单词 This,然后匹配其后的任何字符。如果存在 regs 参数,则匹配寄存器将填充到名为 regs 参数的数组中的 0-10 位置。寄存器 0 将始终包含完全匹配的字符串。有关正则表达式的更多信息,请参见本文档的 正则表达式部分。
eregi 函数与 ereg() 函数相同,只是正则表达式的应用忽略了大小写。
ereg_Replace 函数扫描整个参数字符串,并将与给定表达式匹配的字符串的任何部分替换为替换字符串。例如,在字符串 "This is an example string"
中,我们可以很容易地使用命令 ereg_replace(" ","-","This is an example string") 将每个空格替换为破折号。有关正则表达式的更多信息,请参见本文档的 正则表达式部分。
eregi_replace 函数与 ereg_replace() 函数相同,只是正则表达式的应用忽略了大小写。
EscapeShellCmd 函数转义字符串中可能用于欺骗 shell 命令执行任意命令的任何字符。此函数应用于确保在将来自用户输入的任何数据传递给 Exec() 或 System() 函数之前对其进行转义。标准用法是
<?system(EscapeShellCmd($cmd))>
Eval 函数获取字符串参数的内容,并将其视为一个小型 PHP/FI 脚本。它会将其作为单独的 PHP/FI 脚本执行。从 eval 内部设置或访问的任何变量都将来自 eval 语句在脚本中的当前上下文中全局引用框架。变量替换是在字符串参数上完成的,因此如果要在字符串表达式中使用变量,则应对其进行转义。一些例子
$a = "echo phpversion();"; eval($a); eval("echo phpversion();"); eval("\$a=1; echo \$a;");
Exec 函数执行给定的 unix 命令,但是它不会输出任何内容。它只返回命令结果的最后一行。如果需要执行命令并将命令的所有数据直接返回而没有任何干扰,请使用 PassThru() 函数。如果存在数组参数,则指定的数组将填充 unix 命令的每一行输出,从数组的末尾开始。如果数组中已经包含元素并且想要从数组元素 0 开始填充,请确保在调用之前 UnSet 数组。如果存在 return_var 参数以及数组参数,则执行的 unix 命令的返回状态将写入此变量。请注意,如果要允许来自用户输入的数据传递给此 Exec 函数,则应使用 EscapeShellCmd() 函数,以确保用户无法欺骗系统执行任意命令。另请参见 system() 函数。
Exit 命令用于在解析此标记后立即终止解析。
Exp 函数返回 e 的 arg 次幂。另请参见 pow()
fclose() 函数关闭由 fopen() 函数打开的文件。参数是由 fopen() 调用返回的文件指针索引。
Feof 函数如果文件指针索引参数引用的文件已到达文件末尾,则返回 true。
fgets() 函数从由 fopen() 函数打开的文件中读取一行。参数是由 fopen() 返回的文件指针索引和要读取的最大字节数。读取在读取最大字节数或换行符时结束。这类似于 C fgets() 调用。另请参见 fputs()。
与 fgets() 函数相同,只是此函数在读取文件时尝试剥离任何 HTML 标签或 PHP/FI 脚本标签。
File 函数读取整个文件,并返回一个数组,其中每个数组元素包含文件的一行,从数组索引 0 开始。
fileAtime 函数返回上次数据访问的时间。如果文件不存在,或者由于某种原因无法访问,则此函数返回 -1。如果要重复调用 fileAtime 和其余的 file* 函数,并且要访问的文件可能会更改或消失,则应在调用 file* 函数之前调用 ClearStatCache()。
fileCtime 函数返回上次状态更改的时间。如果文件不存在,或者由于某种原因无法访问,则此函数返回 -1。如果要重复调用 fileCtime 和其余的 file* 函数,并且要访问的文件可能会更改或消失,则应在调用 file* 函数之前调用 ClearStatCache()。
fileGroup 函数返回文件所有者的组 ID。如果文件不存在,或者由于某种原因无法访问,则此函数返回 -1。如果要重复调用 fileGroup 和其余的 file* 函数,并且要访问的文件可能会更改或消失,则应在调用 file* 函数之前调用 ClearStatCache()。
fileInode 函数返回文件的 inode。如果文件不存在,或者由于某种原因无法访问,则此函数返回 -1。如果要重复调用 fileInode 和其余的 file* 函数,并且要访问的文件可能会更改或消失,则应在调用 file* 函数之前调用 ClearStatCache()。
fileMtime 函数返回上次数据修改的时间。如果文件不存在,或者由于某种原因无法访问,则此函数返回 -1。如果要重复调用 fileMtime 和其余的 file* 函数,并且要访问的文件可能会更改或消失,则应在调用 file* 函数之前调用 ClearStatCache()。
fileOwner 函数返回文件所有者的 uid。如果文件不存在,或者由于某种原因无法访问,则此函数返回 -1。如果要重复调用 fileOwner 和其余的 file* 函数,并且要访问的文件可能会更改或消失,则应在调用 file* 函数之前调用 ClearStatCache()。
filePerms 函数返回文件的权限位。这是 Unix C stat 结构的 st_mode 字段。如果文件不存在,或者由于某种原因无法访问,则此函数返回 -1。如果要重复调用 filePerms 和其余的 file* 函数,并且要访问的文件可能会更改或消失,则应在调用 file* 函数之前调用 ClearStatCache()。
fileSize 函数返回文件的大小(以字节为单位)。如果文件不存在,或者由于某种原因无法访问,则此函数返回 -1。如果要重复调用 fileSize 和其余的 file* 函数,并且要访问的文件可能会更改或消失,则应在调用 file* 函数之前调用 ClearStatCache()。
fileType 函数返回文件的类型。返回值可能是:"dir"、"file"、"fifo"、"char"、"block" 或 "link"。它们分别代表目录、普通文件、FIFO 特殊文件、字符特殊文件、块特殊文件和符号链接。
Floor() 函数将浮点数向下取整到最近的整数。返回值的类型为 double(浮点数),以便在复杂的方程式中正确使用。要获得整数类型的返回值,请使用:$new = IntVal(Floor($value));
另见 Ceil()。
Flush() 函数用于刷新输出缓冲区。对于 Apache 模块,它刷新 Apache 的输出缓冲区;对于 CGI 版本,它只刷新标准输出。在 Apache 下以 CGI 运行时,服务器会缓冲 CGI 脚本的输出,因此此 Flush() 函数在此处帮助不大。如果您在 Apache Web 服务器下运行 PHP 的 CGI 版本,请考虑将脚本作为 nph- 脚本运行。或者,运行 PHP 的 Apache 模块版本。
fopen() 函数打开文件并返回文件指针索引。如果无法打开文件,则函数返回 -1。它类似于 C 语言中的 fopen() 调用。filename 参数是待打开文件的相对路径或绝对路径,mode 参数可以是 "r"、"r+"、"w"、"w+"、"a"、"a+" 之一。有关更多信息,请参见 Unix 手册页上的 fopen() 调用说明。另见 popen() 函数说明和 fclose() 函数说明。
示例
$fp = fopen("/home/rasmus/file.txt","r");
fputs() 函数将一行写入由 fopen() 函数打开的文件。参数为 fopen() 返回的文件指针索引和要写入的字符串。请注意,字符串参数可能包含特殊转义字符 \n、\r 和 \t,它们分别用于输出换行符、回车符和制表符。另见 fgets()。
FPassThru() 函数直接输出 *fp* 中所有剩余的数据。它与 ReadFile() 函数的不同之处在于它还可以处理使用 fsockopen() 函数打开的文件。它与 PassThru() 函数的不同之处在于它不处理命令,而是处理打开的文件。FPassThru() 函数返回读取和写入的字节数。
fseek() 函数定位由 $fd 参数标识的文件指针,该参数是 fopen() 函数的返回值。文件指针将定位在文件开头加上 pos 参数指定的偏移量处。另见 ftell() 和 rewind()。
fsockopen() 函数打开套接字连接并返回文件指针索引。此文件指针索引可由 fgets、fputs 和 fclose 函数使用。参数为主机名和端口号。返回值:如果无法创建套接字,则返回 -3;如果主机名上的 DNS 查找失败,则返回 -4;如果连接被拒绝或超时,则返回 -5;如果实际的 fdopen() 调用失败,则返回 -6;如果 setvbuf() 调用失败,则返回 -7。如果端口号为 0,则如果您的操作系统支持 Unix 域套接字,则主机名参数将被视为 Unix 域套接字的文件名。
ftell() 函数返回由 fp 参数标识的文件指针的位置,该参数是 fopen() 函数的返回值。该位置稍后可用作 fseek() 函数的参数。另见 fseek() 和 rewind()。
getAccDir() 函数返回 PHP 访问配置文件所在的目录。访问配置文件的文件名来自其代表的用户用户的数字用户 ID。
GetEnv() 函数返回由 *string* 指定的环境变量的值。通常不使用此函数,因为环境变量可以直接用于 PHP/FI。如果引用在内部符号表中找不到的变量,则会自动搜索环境空间。当需要确保环境变量未被正常的 PHP/FI 变量覆盖时,应使用 GetEnv() 函数。依赖于 HTTP 服务器定义的变量(如 REMOTE_ADDR 和 REMOTE_HOST)的安全机制应使用 GetEnv() 函数加载这些变量,而不是直接引用它们(如 $REMOTE_ADDR),以避免有人伪造表单并将数据发布到您的服务器,从而绕过您可能拥有的任何安全机制。
getHostByName() 函数将给定的域名转换为 nnn.nnn.nnn.nnn 格式的 IP 地址。
getHostByAddr() 函数将给定的 nnn.nnn.nnn.nnn 格式的 IP 地址转换为完全限定的域名。
GetImageSize() 函数采用完整路径文件名或相对于调用脚本位置的相对路径。它返回一个包含宽度、高度和类型的 3 元素数组。宽度和高度以像素为单位,类型 1 表示 GIF 文件,类型 2 表示 JPG 文件,类型 3 表示 PNG 文件。不支持其他文件类型。返回数组中的第四个元素是一个字符串,包含 "width=x height=y",可以直接用于 IMG 标记中。需要注意的是,使用此函数不需要 GD 图像库。以下是一个示例。
<? $result = GetImageSize("img/flag.jpg"); > <IMG SRC="img/flag.jpg" ?echo $result[3]> >
getLastAccess() 函数返回上次访问当前页面的日期和时间(Unix 时间格式)。此值可以传递给 Date() 函数进行格式化。
只有在编译 PHP 时启用了访问日志记录功能时,此函数才可用。
getLastBrowser() 函数返回上次访问当前页面的用户使用的浏览器的标识字符串。
只有在编译 PHP 时启用了访问日志记录功能时,此函数才可用。
getLastEmail() 函数返回上次访问当前页面的用户的电子邮件地址。
只有在编译 PHP 时启用了访问日志记录功能时,此函数才可用。
getLastHost() 函数返回上次访问当前页面的用户的 hostname。
只有在编译 PHP 时启用了访问日志记录功能时,此函数才可用。
getLastMod() 函数返回上次修改当前页面的日期和时间(Unix 时间格式)。此值可以传递给 Date() 函数进行格式化。
只有在编译 PHP 时启用了访问日志记录功能时,此函数才可用。
getLastRef() 函数返回上次访问当前页面的用户的引用文档的 URL。
只有在编译 PHP 时启用了访问日志记录功能时,此函数才可用。
getLogDir() 函数返回可以找到 PHP 日志文件的顶级目录。实际的日志文件位于此目录下的子目录中。每个子目录都是日志文件所属用户的数字用户 ID。然后,在每个目录中都可以找到一系列 dbm 日志文件,每个文件都以其表示的文件的数字 inode 作为文件名的主要组成部分。
getMyInode() 函数返回当前 HTML 文件的数字 inode。
getMyPid() 函数返回 PHP 解析进程的当前进程 ID。
getMyUid() 函数返回当前 HTML 文件所有者的数字用户 ID。
getRandMax() 函数返回 Rand 函数将返回的最大随机数。如果返回的值似乎不准确,请查看 PHP 发行版中的 php.h 源文件以获取更多信息。
getStartLogging() 函数返回当前页面开始记录日志的日期和时间(Unix 时间格式)。当使用基于 mSQL 的日志记录时,这更准确,因为每个日志文件中都保留了一个时间戳。对于 dbm 日志记录,返回的时间是创建用户日志目录的时间。
getToday() 函数返回自当地时间午夜 12 点以来当前页面获得的总点击次数。
只有在编译 PHP 时启用了访问日志记录功能时,此函数才可用。
getTotal() 函数返回自页面上开始访问日志记录以来当前页面获得的总点击次数。
只有在编译 PHP 时启用了访问日志记录功能时,此函数才可用。
GetType() 函数返回变量的类型。返回值是一个字符串,可以是 "integer"、"double" 或 "string" 之一。另见 SetType() 函数。
gmDate() 函数与 Date 函数相同,只是它使用格林威治标准时间而不是当前本地时间。
Header() 命令用于 HTML 文件顶部发送原始 HTTP 头字符串。有关原始 HTTP 头的更多信息,请参见 HTTP 规范。请记住,必须在发送任何实际输出(通过普通的 HTML 标记或 PHP echo 命令)之前使用 Header() 命令。
在 HTTP 身份验证 部分可以找到使用示例。
HexDec() 函数将十六进制字符串转换为十进制数。另见 DecHex() 函数。
HtmlSpecialChars() 函数将字符串参数中 ASCII 码在 160 到 255(含)之间的任何字符转换为其对应的 HTML 实体名称。该函数返回转换后的字符串。<、>、& 和 " 也将被转换。
ImageArc() 函数在由 im 表示的图像中绘制一个以 cx,cy 为中心的椭圆的一部分(左上角为 0,0)。w 和 h 分别指定椭圆的宽度和高度,起始点和结束点以度数表示,由 s 和 e 参数指示。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageChar() 函数在由 im 标识的图像中,以颜色 col 在坐标 x,y(左上角为 0,0)处绘制字符 c。size 参数可以是 1、2、3、4 或 5,表示要使用的字体大小。1 为最小,5 为最大。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageCharUp() 函数在由 im 标识的图像中,以颜色 col 在坐标 x,y(左上角为 0,0)处垂直绘制字符 c。size 参数可以是 1、2、3、4 或 5,表示要使用的字体大小。1 为最小,5 为最大。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageColorAllocate() 函数返回一个颜色标识符,表示由给定的 RGB 分量组成的颜色。im 参数是 ImageCreate 函数的返回值。必须调用 ImageColorAllocate() 函数来创建要在 im 表示的图像中使用的每种颜色。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageColorTransparent() 函数将 im 图像中的透明颜色设置为 col。im 是 ImageCreate 函数返回的图像标识符,col 是 ImageColorAllocate 函数返回的颜色标识符。只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageCopyResized() 函数将一个图像的矩形部分复制到另一个图像。dst_im 是目标图像,src_im 是源图像标识符。如果源坐标和目标坐标以及宽度和高度不同,则将执行图像片段的适当拉伸或缩小。坐标指左上角。此函数可用于复制同一图像内的区域(如果 dst_im 与 src_im 相同),但如果区域重叠,则结果不可预测。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageCreate 返回一个图像标识符,代表一个大小为 x_size x y_size 的空白图像。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageCreateFromGif 返回一个图像标识符,代表从给定 *filename* 获取的图像。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageDestroy 释放与图像 im 相关联的任何内存。im 是 ImageCreate 函数返回的图像标识符。只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageFill 执行从坐标 x,y (左上角为 0,0) 开始的漫水填充,在图像 im 中使用颜色 col。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageFilledPolygon 在图像 im 中创建一个填充的多边形。points 是一个包含多边形顶点的 PHP 数组。例如:points[0] = x0, points[1] = y0, points[2] = x1, points[3] = y1 等。num_points 是顶点的总数。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageFilledRectangle 在图像 im 中创建一个填充的矩形,颜色为 col,从左上角坐标 x1,y1 开始,到右下角坐标 x2,y2 结束。0,0 是图像的左上角。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageFillToBorder 执行漫水填充,其边界颜色由 border 定义。填充的起点是 x,y (左上角为 0,0),区域填充颜色为 col。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageGif 从图像 im 创建 GIF 文件 filename。im 参数是 ImageCreate 函数的返回值。filename 参数是可选的,如果省略,则会直接返回原始图像流。通过使用 Header() 函数发送 *image/gif* 内容类型,您可以创建一个 PHP/FI 脚本,该脚本使用此函数直接返回 GIF 图像。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageInterlace 打开或关闭隔行扫描位。如果 interlace 为 1,则 im 图像将进行隔行扫描;如果 interlace 为 0,则隔行扫描位将关闭。只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageLine 在图像 im 中绘制一条从 x1,y1 到 x2,y2 (左上角为 0,0) 的线,颜色为 col。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImagePolygon 在图像 im 中创建一个多边形。points 是一个包含多边形顶点的 PHP 数组。例如:points[0] = x0, points[1] = y0, points[2] = x1, points[3] = y1 等。num_points 是顶点的总数。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageRectangle 在图像 im 中创建一个矩形,颜色为 col,从左上角坐标 x1,y1 开始,到右下角坐标 x2,y2 结束。0,0 是图像的左上角。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageSetPixel 在图像 im 中的 x,y (左上角为 0,0) 处绘制一个像素,颜色为 col。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageString 在由 im 标识的图像中,在坐标 x,y (左上角为 0,0) 处绘制字符串 s,颜色为 col。size 参数可以是 1、2、3、4 或 5,表示要使用的字体的尺寸。1 最小,5 最大。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageStringUp 在由 im 标识的图像中,在坐标 x,y (左上角为 0,0) 处垂直绘制字符串 s,颜色为 col。size 参数可以是 1、2、3、4 或 5,表示要使用的字体的尺寸。1 最小,5 最大。
只有在 PHP 中启用了 GD 支持时,此函数才可用。
ImageSX 返回由 *im* 标识的图像的宽度。
ImageSY 返回由 *im* 标识的图像的高度。
Include 命令可用于将其他文件插入到当前 html 文件中。这对于可能需要包含在数百个 HTML 文件中的页眉和页脚非常方便。通过使用 include 命令,您只需要在一个地方修改页眉或页脚文件即可进行更改。由于对包含的文件进行了完整的 PHP 解析,您还可以使用 include 命令包含您可能编写的常用 PHP 脚本。这有点像拥有一个您可以从 HTML 文件调用的脚本的原始共享库。您可以将此类常用库文件放在一个目录中,并设置 PHP 的 include 路径,而无需使用路径名引用这些文件。对于 Apache 模块用户,可以使用 **phpIncludePath** 指令进行配置;对于 CGI 用户,可以使用 PHP_INCLUDE_PATH 环境变量。此路径用冒号分隔,就像您 UNIX shell 中的 $PATH
一样。例如:
<?include("/path/filename.txt")>
InitSyslog() 定义使用 OpenLog() 和 Syslog() 时需要的一些 PHP 变量。出于效率原因,这些变量默认情况下未定义。变量的命名方式与 <syslog.h> C include 文件中的相同(例如 $LOG_LOCAL0)。有关更多详细信息,请参阅您的 syslog(3) UNIX 手册页。另请参阅 InitSyslog()、Syslog() 和 CloseLog()。
intval 返回变量的长整数值。另请参阅 strval() 和 doubleval() 函数。
IsSet 函数如果给定变量已定义,则返回 1;如果未定义,则返回 0。
Key 返回当前数组项的键。当前项由给定变量的数组指针的位置确定。可以使用 Reset()、End()、Next() 和 Prev() 函数操作此数组指针。此函数主要用于确定关联数组中项的键值,尽管它也适用于普通数组。
Link() 创建硬链接。有关创建符号链接(软链接),请参阅 Symlink() 函数。另请参阅 ReadLink 和 LinkInfo 函数。
LinkInfo 返回 lstat 系统调用返回的 UNIX C stat 结构的 st_dev 字段。此函数用于验证链接(path 指向)是否确实存在(使用与 stat.h 中定义的 S_ISLNK 宏相同的方法)。如果出错,则返回 -1。
Log 返回 arg 的自然对数。
Log10 返回 arg 的以 10 为底的对数。
LogAs() 函数将当前页面的点击次数视为实际上是在参数 filename 上接收到的。
Mail 自动将 message 参数中指定的邮件发送到 to 参数中指定的接收者。可以通过在 to 参数中的多个接收者之间用空格来指定多个接收者。
例如:
mail("[email protected]", "My Subject", "Line 1\nLine 2\nLine 3");如果传递第四个字符串参数,则此字符串将插入到标头的末尾,例如
mail("[email protected]", "the subject", $message, "X-Mailer: PHP/FI " + phpversion());
Max 返回 PHP 数组的最大值。即,它将搜索整个数组以查找最大元素。如果它是字符串数组,则返回的字符串是在数组排序后字母顺序上排在最后面的字符串。
Md5 返回字符串值的 MD5 哈希值。
mi_Close 将关闭与给定连接标识符关联的 Illustra 数据库的连接。
只有在 PHP 中启用了 Illustra 支持时,此函数才可用。
mi_Connect 打开与 Illustra 数据库的连接。每个参数都应该是一个带引号的字符串。此函数返回一个 connection_id。其他 Illustra 函数需要此标识符。您可以同时打开多个连接。要连接到的主机由运行 PHP 可执行文件的机器上的 MI_PARAMS 文件控制。目前尚不支持远程调用。此函数在出错时将返回 **-1**。
只有在 PHP 中启用了 Illustra 支持时,此函数才可用。
mi_DBname 将返回给定 Illustra 连接标识符连接到的数据库的名称。
只有在 PHP 中启用了 Illustra 支持时,此函数才可用。
mi_Exec 将 SQL 语句发送到由 connection_id 指定的 Illustra 数据库。connection_id 必须是由 mi_Connect 返回的有效标识符。此函数的返回值是一个标识符,用于访问其他 Illustra 函数的结果。此函数在出错时将返回 **-1**。
只有在 PHP 中启用了 Illustra 支持时,此函数才可用。
mi_FieldName 将返回在给定的 Illustra 结果和连接标识符中占据给定列号的字段的名称。字段编号从 0 开始。
此函数在出错时将返回 **-1**。
只有在 PHP 中启用了 Illustra 支持时,此函数才可用。
mi_FieldNum 将返回与给定 Illustra 结果标识符中命名的字段对应的列槽的编号。字段编号从 0 开始。此函数在出错时将返回 **-1**。
只有在 PHP 中启用了 Illustra 支持时,此函数才可用。
mi_NumFields 将返回 Illustra 结果中的字段(列)数。该参数是由 mi_Exec 返回的有效结果标识符。此函数在出错时将返回 **-1**。
只有在 PHP 中启用了 Illustra 支持时,此函数才可用。
mi_NumRows 将返回 Illustra 结果中的行数。该参数是由 mi_Exec 返回的有效结果标识符。此函数在出错时将返回 **-1**。
只有在 PHP 中启用了 Illustra 支持时,此函数才可用。
mi_Result 将返回由 mi_Exec 生成的结果标识符中的值。row_number 和字段名称指定要返回的结果表中的哪个单元格。行编号从 0 开始。您可以使用未加引号的数字代替命名字段。字段索引从 0 开始。
由于目前没有类型检测,因此从数据库返回的所有值都为字符串形式。
只有在 PHP 中启用了 Illustra 支持时,此函数才可用。
Microtime() 返回一个字符串“msec sec”,其中 sec 是自 1970 年 1 月 1 日 00:00 GMT 以来经过的秒数,msec 是微秒部分(作为秒的分数)。例如“0.87633900 825010464”。
此函数仅在支持 gettimeofday() 系统调用的操作系统上可用。
Min 函数返回 PHP 数组中的最小值。例如,它将搜索整个数组以查找最小元素。如果它是字符串数组,则返回的字符串是在数组排序时字母顺序最前的字符串。
MkDir 创建一个目录。mode 参数必须使用 八进制 表示法。例如:MkDir("DirName",0755);
MkTime 返回一个 Unix 时间戳(长整型)格式的时间,该时间对应于参数指定的日期和时间。可以省略参数,在这种情况下,给定组件将根据当前本地时间和日期设置为当前值。这些省略的参数只能从右到左省略。例如,MkTime(hour,min,sec)
是有效的,但 MkTime(mon,day,year)
是无效的。请注意,此函数作为执行日期算术和日期验证的工具非常方便。您可以向其提供无效参数,例如大于 12 的月份或大于 31 的日期,它仍然会计算出正确的日期。如果任何参数超出正常值,它还会生成错误消息。使用 SetErrorReporting(0) 函数在调用此函数之前关闭此错误报告,然后您可以检查 $phperrmsg 中是否发生任何错误。
例如:
SetErrorReporting(0); $a = MkTime(0,0,0,13,1,1997); SetErrorReporting(1); echo $phperrmsg;
msql 发送 mSQL 查询。参数是数据库名称和查询字符串。例如:<?msql("MyDatabase" , "select * from table")>
。此函数的返回值是一个结果标识符,用于访问其他 msql_ 函数的结果。结果标识符是一个正整数。当未创建结果标识符时,函数返回0。对于任何不返回任何内容的查询,例如create、update、drop、insert 和 delete,都是这种情况。如果发生错误,函数将返回-1。描述错误的字符串将放入 $phperrmsg 中,除非该函数被调用为@msql(),否则此错误字符串也将被打印出来。对于 mSQL 2.0,$result 变量将包含 SQL 命令执行所影响的行数。如果您希望您的应用程序可移植到 mSQL 1.0,请不要依赖此功能。
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
如果存在打开的连接,msql_Close 将关闭与 msql 守护程序的套接字连接。请注意,由于一次只能打开一个并发 mSQL 会话,因此此函数不带参数。
msql_Connect 指定驻留 mSQL 数据库引擎的主机名或 IP。这等效于 mSQL C API 中的 msqlConnect() 函数。此函数与 C API 等效项之间的一个区别是,如果未调用此函数,则在第一次调用 msql() 函数时默认连接到本地主机。并且,不需要 msql_close 函数,因为一次只能激活一个连接。如果在一个文件中第二次调用 msql_connect(),则与第一个主机的连接将自动关闭。要显式连接到本地主机上的 msql 守护程序,请使用:<?msql_connect("localhost")>
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
msql_CreateDB 创建给定的数据库。
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
msql_dbName 返回从 msql_ListDbs() 函数返回的结果指针的 $i 位置中存储的数据库名称。msql_NumRows() 函数可用于确定有多少个数据库名称可用。
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
msql_DropDB 删除给定的 mSQL 数据库。请谨慎使用此功能,因为数据库中的所有数据都将丢失。
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
msql_FieldFlags 返回指定字段的字段标志。目前,这可以是“not null”、“primary key”,两者的组合或“” (空字符串)。
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
msql_FieldLen 返回指定字段的长度。
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
msql_FieldName 返回指定字段的名称。函数的参数是结果标识符和字段索引。例如,msql_FieldName($result,2);
将返回与结果标识符关联的结果中第二个字段的名称。
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
msql_FieldType 与 msql_FieldName() 函数类似。参数相同,但返回字段类型。这将是“int”、“char”或“real”之一。
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
只有当您担心在脚本运行时使用过多内存时,才需要调用 msql_FreeResult。所有结果内存都将在脚本结束后自动释放。但是,如果您确定在脚本中不再需要结果数据,则可以使用结果标识符作为参数调用 msql_freeresult,并且将释放关联的结果内存。
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
msql_ListDBs 将返回一个结果指针,其中包含当前 mSQL 守护程序可用的数据库。使用 msql_dbName() 函数遍历此结果指针。
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
msql_listfields 检索有关给定 tablename 的信息。参数是数据库名称和表名称。返回一个结果指针,可与 msql_fieldflags、msql_fieldlen、msql_fieldname、msql_fieldtype 一起使用。结果标识符是一个正整数。如果发生错误,函数返回 -1。描述错误的字符串将放入 $phperrmsg 中,除非该函数被调用为 @msql(),否则此错误字符串也将被打印出来。
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
msql_ListTables 获取数据库名称和结果指针,就像 msql() 函数一样。msql_TableName() 函数应该用于从结果指针中提取实际的表名。
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
msql_NumFields 返回结果中的字段数。参数是 msql() 函数返回的结果标识符。
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
msql_NumRows 只返回结果中的行数。参数是 msql() 函数返回的结果标识符。
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
msql_RegCase 获取字符串参数并将其转换为需要发送到 mSQL 以获得不区分大小写的匹配的正则表达式。这将像“abc”这样的字符串转换为“[Aa][Bb][Cc]”。
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
msql_Result 显示返回记录中的字段。参数是 msql() 函数返回的结果标识符,一个整数,它是要查看的记录的索引,以及一个字段名称。字段参数支持“table.field”语法,用于处理来自联接的结果。此函数最好用完整的示例来说明。
<? $name = "bob"; $result = msql($database,"select * from table where firstname='$name'"); $num = msql_numrows($result); echo "$num records found!<p>"; $i=0; while($i<$num); echo msql_result($result,$i,"fullname"); echo "<br>"; echo msql_result($result,$i,"address"); echo "<br>"; $i++; endwhile; >
上面的脚本连接到本地机器上的 mSQL 引擎,将name 变量设置为bob,并发送一个查询,该查询请求来自firstname 字段设置为bob 的表的全部字段。然后,它显示它找到的记录数,之后它遍历每个找到的记录并显示每个记录的fullname 和address 字段。正如您所看到的,在打印的字段周围添加 HTML 标记以表格或任何所需的方式格式化结果将是小菜一碟。请注意,没有 msql_connect() 调用。只有在需要连接到远程数据库时才需要调用 msql_connect。
仅当在 PHP 中启用 mSQL 支持时,此函数才可用。
msql_TableName 获取 msql_ListTables() 函数返回的结果指针以及整数索引,并返回表名。msql_NumRows() 函数可用于确定结果指针中的表数。一个例子是
<? $result = msql_listtables("dbname"); $i=0; while($i < msql_numrows($result)); $tb_names[$i]=msql_tablename($result, $i); echo $tb_names[$i]; echo "<BR>"; $i++; endwhile; >
mysql 发送 mysql 查询。参数是数据库名称和查询字符串。例如:<?mysql("MyDatabase" , "select * from table")>
。此函数的返回值是一个结果标识符,用于访问其他 mysql_ 函数的结果。结果标识符是一个正整数。当未创建结果标识符时,函数返回0。对于任何不返回任何内容的查询,例如create、update、drop、insert 和 delete,都是这种情况。如果发生错误,函数将返回-1。描述错误的字符串将放入 $phperrmsg 中,除非该函数被调用为@mysql(),否则此错误字符串也将被打印出来。
仅当在 PHP 中启用 mysql 支持时,此函数才可用。
mysql_affected_rows() 返回上次 INSERT、UPDATE 或 DELETE 查询所影响的行数。
mysql_Close 关闭与 mysql 守护程序的套接字连接(如果存在打开的连接)。
mysql_Connect 指定驻留 mysql 数据库引擎的主机名或 IP。这等效于 mysql C API 中的 mysqlConnect() 函数。此函数与 C API 等效项之间的一个区别是,如果未调用此函数,则在第一次调用 mysql() 函数时默认连接到本地主机。并且,不需要 mysql_close 函数,因为一次只能激活一个连接。如果在一个文件中第二次调用 mysql_connect(),则与第一个主机的连接将自动关闭。
可以提供可选的用户名和密码。请注意,当 PHP 编译为在 安全模式 下运行时,用户名必须与正在处理的文件的所有者相同,或者与 httpd 进程的所有者相同(通常是 nobody)。任何其他用户名都将失败。
要显式连接到本地主机上的 mysql 守护程序,请使用:<?mysql_connect("localhost")>
仅当在 PHP 中启用 mysql 支持时,此函数才可用。
mysql_CreateDB 创建给定的数据库。
仅当在 PHP 中启用 mysql 支持时,此函数才可用。
mysql_dbName 返回从 mysql_ListDbs() 函数返回的结果指针的 $i 位置中存储的数据库名称。mysql_NumRows() 函数可用于确定有多少个数据库名称可用。
仅当在 PHP 中启用 mysql 支持时,此函数才可用。
mysql_DropDB 删除给定的 mysql 数据库。请谨慎使用此功能,因为数据库中的所有数据都将丢失。
仅当在 PHP 中启用 mysql 支持时,此函数才可用。
mysql_FieldFlags 返回指定字段的字段标志。目前,这可以是“not null”、“primary key”,两者的组合或“” (空字符串)。
仅当在 PHP 中启用 mysql 支持时,此函数才可用。
mysql_FieldLen 返回指定字段的长度。
仅当在 PHP 中启用 mysql 支持时,此函数才可用。
mysql_FieldName 返回指定字段的名称。函数的参数是结果标识符和字段索引。例如,mysql_FieldName($result,2);
将返回与结果标识符关联的结果中第二个字段的名称。
仅当在 PHP 中启用 mysql 支持时,此函数才可用。
mysql_FieldType 与 mysql_FieldName() 函数类似。参数相同,但返回字段类型。这将是“int”、“char”或“real”之一。
仅当在 PHP 中启用 mysql 支持时,此函数才可用。
只有当您担心在脚本运行时使用过多内存时,才需要调用 mysql_FreeResult。所有结果内存都将在脚本结束后自动释放。但是,如果您确定在脚本中不再需要结果数据,则可以使用结果标识符作为参数调用 mysql_freeresult,并且将释放关联的结果内存。
仅当在 PHP 中启用 mysql 支持时,此函数才可用。
mysql_insert_id() 返回 AUTO_INCREMENT 字段生成的 ID。此函数不接受任何参数。它将返回最后执行的 INSERT 查询返回的自动生成的 ID。
mysql_ListDBs 将返回一个结果指针,其中包含当前 mysql 守护进程可用的数据库。使用 mysql_dbName() 函数遍历此结果指针。
仅当在 PHP 中启用 mysql 支持时,此函数才可用。
mysql_listfields 获取关于给定表名的信息。参数是数据库名称和表名称。返回一个结果指针,可与 mysql_fieldflags、mysql_fieldlen、mysql_fieldname、mysql_fieldtype 一起使用。结果标识符是一个正整数。如果发生错误,则函数返回 -1。描述错误的字符串将被放入 $phperrmsg 中,除非函数被调用为 @mysql(),否则此错误字符串也将被打印出来。
仅当在 PHP 中启用 mysql 支持时,此函数才可用。
mysql_ListTables 获取数据库名称和结果指针,类似于 mysql() 函数。mysql_TableName() 函数应该用于从结果指针中提取实际的表名。
仅当在 PHP 中启用 mysql 支持时,此函数才可用。
mysql_NumFields 返回结果中的字段数。参数是 mysql() 函数返回的结果标识符。
仅当在 PHP 中启用 mysql 支持时,此函数才可用。
mysql_NumRows 简单地返回结果中的行数。参数是 mysql() 函数返回的结果标识符。
仅当在 PHP 中启用 mysql 支持时,此函数才可用。
mysql_Result 显示返回记录中的一个字段。参数是 mysql() 函数返回的结果标识符,一个整数,表示要查看的记录的索引,以及一个字段名称。字段参数支持“table.field”语法,用于处理来自连接的结果。mSQL 1.0 和 mysql 之间的一个区别是 mysql 支持可以作用于结果数据的函数。这些函数可以应用于此函数。此函数最好通过一个完整的示例来说明。
<? $name = "bob"; $result = mysql($database,"select * from table where firstname='$name'"); $num = mysql_numrows($result); echo "$num records found!<p>"; $i=0; while($i<$num); echo mysql_result($result,$i,"lcase(fullname)"); echo "<br>"; echo mysql_result($result,$i,"address"); echo "<br>"; $i++; endwhile; >
上面的脚本连接到本地机器上的 mysql 引擎,将name变量设置为bob,并发送一个查询,该查询请求一个firstname字段设置为bob的表中的所有字段。然后,它显示找到的记录数,之后它循环遍历每个找到的记录,并显示每个记录的fullname和address字段。result 函数中的 lcase() 调用将返回的字符串更改为小写。有关可以应用于结果数据的完整函数集,请参阅您的 mysql 文档。如您所见,在打印的字段周围添加 HTML 标记以表格或任何所需的方式格式化结果将非常简单。请注意,没有 mysql_connect() 调用。只有在需要连接到远程数据库时才需要调用 mysql_connect()。
仅当在 PHP 中启用 mysql 支持时,此函数才可用。
mysql_TableName 获取 mysql_ListTables() 函数返回的结果指针以及一个整数索引,并返回表名。mysql_NumRows() 函数可用于确定结果指针中的表数。一个例子是
<? $result = mysql_listtables("dbname"); $i=0; while($i < mysql_numrows($result)); $tb_names[$i]=mysql_tablename($result, $i); echo $tb_names[$i]; echo "<BR>"; $i++; endwhile; >
Next 将内部数组指针移动到数组中的下一项。当使用非索引方法($array[])访问数组时,这会自动发生。该函数返回新项目的value。此函数可用于向前移动指针,而无需显式访问数组。一种用途是遍历关联数组,只打印出数组的键,而不打印实际的内容。
<? Reset($array); $i=0; while($i < count($array)); echo key($array); next($array); $i++; endwhile; >
OctDec 将八进制数转换为十进制数。另见 DecOct()。
openDir 打开指定的目录并将内部指针置于目录的开头。使用 readDir 函数读取目录条目,并且应该使用 closeDir 函数关闭打开的目录。
OpenLog() 初始化系统以进行进一步的 Syslog() 调用。有关更多详细信息,请参阅 openlog(3) UNIX 手册页。另见 InitSyslog()、Syslog() 和 CloseLog()。
这是一个 Ora_Bind() 使用示例
/* This is the PHP variable to be bound */ $rc = "12345"; /* This is the SQL query. */ $query = "SELECT * FROM my_table where my_index = :indiana"; ........ if (Ora_Parse($cursor, $query) < 0) { echo("Parse failed!\n" Ora_Logoff($conn); exit; } if (Ora_Bind($cursor, "rc", ":indiana", strlen($rc)) < 0) { echo("Binding failed!\n" Ora_Logoff($conn); exit; } /* Execute the SQL statement associated with $cursor and prepare storage for select-list items. */ $ncols = Ora_Exec($cursor); ......
Ord 返回 arg 的第一个字符的 ASCII 值。
Parse_str 获取与常规 URL 编码字符串相同的字符串,并提取变量及其值。
例如。
<? parse_str("a[]=hello+world&a[]=second+variable"); echo $a[],"<br>"; echo $a[],"<br>"; > produces hello world second variable
PassThru() 函数类似于 Exec() 函数,因为它执行 Unix 命令。如果存在 return_var 参数,则 Unix 命令的返回状态将放置在此处。当 Unix 命令的输出是需要直接传递回浏览器的二进制数据时,应使用此命令代替 Exec 或 System。这的一个常见用途是执行诸如 pbmplus 实用程序之类的程序,这些程序可以直接输出图像流。通过将内容类型设置为image/gif,然后调用 pbmplus 程序输出 gif,您可以创建直接输出图像的 PHP/FI 脚本。
Pclose 关闭使用 popen() 函数打开的管道。
pg_Close 将关闭与给定连接标识符关联的 Postgres 数据库的连接。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
pg_Connect 打开与 Postgres 数据库的连接。每个参数都应该是一个带引号的字符串,包括端口号。options 和 tty 参数是可选的,可以为空字符串。此函数返回一个 connection_id。其他 Postgres 函数需要此标识符。您可以同时打开多个连接。此函数在出错时将返回0。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
pg_DBname 将返回给定 Postgres 连接标识符连接到的数据库的名称。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
如果在存在有效连接的最后一个数据库操作上发生错误,则此函数将返回一个包含后端服务器生成的错误消息的字符串。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
pg_Exec 将 SQL 语句发送到 connection_id 指定的 Postgres 数据库。connection_id 必须是 pg_Connect 返回的有效标识符。此函数的返回值是用于访问其他 Postgres 函数结果的标识符。此函数在出错时将返回0。当命令正确执行但预期不会返回数据(例如 insert 或 update 命令)时,它将返回1。请注意,不返回数据的 select 仍然会返回大于 1 的有效结果。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
pg_FieldName 将返回在给定的 Postgres 结果标识符中占据给定列号的字段的名称。字段编号从 0 开始。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
pg_FieldPrtLen 将返回 Postgres 结果中特定值的实际打印长度(字符数)。行编号从 0 开始。此函数在出错时将返回-1。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
pg_FieldNum 将返回与给定 Postgres 结果标识符中命名的字段对应的列槽号。字段编号从 0 开始。此函数在出错时将返回-1。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
pg_FieldSize 将返回给定 Postgres 结果中命名字段的内部存储大小(以字节为单位)。字段大小为 0 表示可变长度字段。此函数在出错时将返回-1。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
pg_FieldType 将返回一个包含给定 Postgres 结果标识符中给定字段的类型名称的字符串。字段编号从 0 开始。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
只有当您担心在脚本运行时使用过多的内存时,才需要调用 pg_FreeResult。所有结果内存将在脚本完成后自动释放。但是,如果您确定在脚本中不再需要结果数据,则可以使用结果标识符作为参数调用 pg_freeresult,并且将释放关联的结果内存。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
如果最后一条通过 pg_Exec 发送的命令是 SQL Insert 命令,则可以使用 pg_GetLastOid 来检索分配给插入元组的 Oid。如果存在有效的 Oid,则此函数将返回一个正整数。如果发生错误或最后一条通过 pg_Exec 发送的命令不是 Insert 命令,则它将返回 **-1**。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
pg_Host 将返回给定 Postgres 连接标识符所连接到的主机名。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
pg_NumFields 将返回 Postgres 结果中的字段(列)数。参数是 pg_Exec 返回的有效结果标识符。此函数在发生错误时将返回 **-1**。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
pg_NumRows 将返回 Postgres 结果中的行数。参数是 pg_Exec 返回的有效结果标识符。此函数在发生错误时将返回 **-1**。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
pg_Options 将返回一个字符串,其中包含给定 Postgres 连接标识符上指定的选项。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
pg_Port 将返回给定 Postgres 连接标识符所连接到的端口号。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
pg_Result 将从 pg_Exec 生成的结果标识符中返回值。行号和字段名称指定要返回的结果表中的哪个单元格。行号从 0 开始。您可以使用未加引号的数字作为字段索引,而不是命名字段。字段索引从 0 开始。
Postgres 有许多内置类型,这里只直接支持基本类型。所有类型的整数、布尔值和 oid 类型都作为整数值返回。所有类型的浮点数和实数类型都作为双精度值返回。所有其他类型(包括数组)都作为字符串返回,其格式与您在“monitor”或“psql”程序中看到的 Postgres 默认格式相同。
计划在以后的日期支持从 Postgres 结果返回数值和字符串数据的 PHP 数组。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
pg_tty 将返回服务器端调试输出发送到的 tty 名称,该名称位于给定的 Postgres 连接标识符上。
仅当在 PHP 中启用了 Postgres 支持时,此函数才可用。
phpInfo 打印与您在 PHP/FI 解析的 URL 中添加“?info”时或单独运行 php.cgi 二进制文件时获得的页面相同的页面。它对于调试 Apache 模块版本中的脚本特别有用,因为它显示了许多有用的内部数据。
phpVersion 返回当前运行的 PHP/FI 的版本号。
Popen 打开到命令的管道并返回文件指针索引。此文件指针索引可由 fgets、fputs 和 fclose 使用。参数是要运行的命令和模式。模式可以是“r”(读取)或“w”(写入)。有关更多详细信息,请参阅 UNIX C 库 popen 手册页。任何使用 popen() 打开的文件都应使用 pclose() 函数关闭。
Pos() 函数返回数组元素在该数组中的数值位置。这对于普通数组不太有用,但对于关联数组来说可能很方便。
计算 x 的 y 次幂。另请参见 Exp()
Prev 将给定变量的内部数组指针移动到数组中的前一项。如果已经在列表的开头,则指针将指向第一项。该函数返回新项目的 value。此函数可用于反向遍历关联数组。请参阅 End() 定义中的示例。另请参见 Next()。
PutEnv 将给定字符串放入环境中。这并非非常有用,因为在 PHP 完成页面处理后,本地环境变量会被清除,但在某些情况下,如果从 PHP 脚本内部调用的其他内容检查环境变量,则它很有用。例如,如果您想运行多个 mSQL 守护程序进程,则需要使用 PutEnv 在不同的套接字之间切换。
QuoteMeta 返回一个字符串,该字符串由 arg 组成,其中任何正则表达式特殊字符都用反斜杠转义。
Rand 返回 0 到 RANDMAX 之间的随机数。**请记住**在调用 rand() 之前使用 srand() 调用来播种随机数生成器。您只需要播种一次随机数生成器。可以使用 getRandMax 函数确定 RANDMAX。通常,通过简单地对结果使用模运算符来选择特定范围。
readDir 读取当前打开的目录结构中的下一项。读取一项后,指针将前进到目录中的下一项,此函数的下一个调用将返回目录中的下一项。在调用此函数之前,使用 openDir 函数打开目录。
$size = ReadFile(Filename) - 读取文件 filename 并直接输出。它返回实际读取的字节数。它与 File() 命令的不同之处在于它不将文件存储在内存中,并且可以安全地用于二进制文件。此函数通常用于可能执行 PassThru("cat filename") 的地方。使用 ReadFile 更有效。
此函数已被 ereg() 函数取代。但是,它仍然可用以实现向后兼容性。
如果在参数字符串中匹配正则表达式,则 reg_Match 返回非零值。例如,条件<?if (reg_match("^This.*", "This is an example string")>
将为真,因为 "^This.*" 表达式表示匹配字符串开头的单词 **This**,然后匹配其后的任何字符。如果存在 *regs* 参数,则匹配寄存器将填充到名为 *regs* 参数的数组中的位置 0-10。寄存器 0 将始终包含完全匹配的字符串。有关正则表达式的更多信息,请参阅本文档的 正则表达式部分。
此函数已被 ereg_replace() 函数取代。但是,它仍然可用以实现向后兼容性。
reg_Replace 扫描整个参数字符串,并将给定表达式匹配的字符串的任何部分替换为替换字符串。例如,在字符串"This is an example string"
中,我们可以很容易地使用以下命令将每个空格替换为破折号:**reg_replace(" ","-","This is an example string")**。有关正则表达式的更多信息,请参阅本文档的 正则表达式部分。
此函数已被 ereg() 函数取代。但是,它仍然可用以实现向后兼容性。
reg_Search 将扫描整个参数字符串以查找与给定正则表达式匹配的任何内容。如果找到匹配项,它将返回从匹配发生的位置开始的字符串部分。如果未找到匹配项,则返回零长度字符串。如果存在 *regs* 参数,则匹配寄存器将填充到名为 *regs* 参数的数组中的位置 0-10。寄存器 0 将始终被分配完全匹配的字符串。有关正则表达式的更多信息,请参阅本文档的 正则表达式部分。
将文件名 old 重命名为 new。类似于 Unix C rename() 函数。
Reset 将给定数组变量的内部数组指针移动到数组的第一项,并返回此项的值。这对于遍历关联数组和非索引数组很有用。另请参见 End() 和 Next()。以下示例遍历关联数组
<? Reset($array); $i=0; while($i < count($array)); echo $array[]; /* pointer automatically moves ahead one */ $i++; endwhile; >
Return 退出当前函数调用并将指定值返回给调用方。有关更多信息,请参阅 用户定义函数 部分。
rewind() 重置由 $fd 参数标识的文件指针,该参数是 fopen() 调用的返回值。文件指针位于文件开头。另请参见 ftell() 和 fseek()。
rewindDir 将当前目录指针移回目录的开头。在调用此函数之前,使用 openDir 函数打开目录。
RmDir() 删除给定的目录。有关删除常规文件,请参阅 Unlink() 函数。
SetCookie() 定义一个 cookie,以便与其余标头信息一起发送。除 name 参数外,所有参数都是可选的。如果仅存在 name 参数,则将删除远程客户端中该名称的 cookie。您还可以用空字符串(**""**)替换任何参数以跳过该参数。expire 和 secure 参数是整数,不能用空字符串跳过。改为使用零(**0**)。expire 参数是常规 Unix 时间整数,由 time() 或 mktime() 函数返回。一些例子如下
SetCookie("TestCookie","Test Value"); SetCookie("TestCookie",$value,time()+3600); /* expire in 1 hour */ SetCookie("TestCookie",$value,time()+3600,"/~rasmus/",".utoronto.ca",1);
请注意,cookie 的 value 部分在发送 cookie 时会自动进行 url 编码,并在收到时自动解码并分配给与 cookie 名称相同的名称的变量。即要查看脚本中测试 cookie 的内容,只需执行
echo $TestCookie;
SetErrorReporting 将当前错误报告状态设置为 *arg* 的值。如果非零,则会打印错误,如果为 0,则不会打印错误。该函数返回之前的错误报告状态。这是一种比在单个函数前面加上“@”字符更通用的禁用错误报告的方法。有关更多信息,请参阅 抑制函数调用的错误 部分。
SetLogging() 启用或禁用页面的访问统计信息记录。如果 *arg* 非零,则启用日志记录;如果为零,则禁用日志记录。
SetShowInfo() 启用或禁用所有通过 PHP 加载的页面底部的信息页脚。如果 *arg* 非零,则启用页脚;如果为零,则禁用页脚。
SetType 设置变量的类型。type 参数是“integer”、“double”或“string”之一。另请参见 GetType() 函数。
将值 **n** 左移 **b** 位。
将值 **n** 右移 **b** 位。
Sleep 函数将延迟 secs 秒。类似于 Unix C 的 sleep() 函数。另见 USleep() 函数。
Solid_Close 函数将关闭与给定连接标识符关联的 Solid 服务器连接。
仅当在 PHP 中启用 Solid 支持时,此函数才可用。
Solid_Connect 函数打开与 Solid 服务器的连接。每个参数都应为带引号的字符串。第一个参数(数据源名称)可以为空字符串,这将导致连接到本地主机的默认服务器。此函数返回一个 connection_id。其他 Solid 函数需要此标识符。您可以同时打开多个连接。此函数在出错时将返回 0。
仅当在 PHP 中启用 Solid 支持时,此函数才可用。
Solid_Exec 函数将 SQL 语句发送到由 connection_id 指定的 Solid 服务器。connection_id 必须是由 Solid_Connect 函数返回的有效标识符。此函数的返回值是一个标识符,用于通过其他 Solid 函数访问结果。此函数在出错时将返回 0。当命令正确执行但预期不返回数据(例如 insert 或 update 命令)时,它将返回 1。请注意,不返回数据的 select 查询仍然会返回大于 1 的有效结果。
仅当在 PHP 中启用 Solid 支持时,此函数才可用。
Solid_FetchRow 函数获取由 Solid_Exec 函数返回的数据行。调用 Solid_FetchRow 后,可以使用 Solid_Result 访问该行中的字段。每次调用 Solid_FetchRow 时,都可以通过 Solid_Result 访问新的一行。如果 Solid_FetchRow 成功(存在新行),则返回 1;如果没有更多行,Solid_FetchRow 将返回 0。Solid_FetchRow 的返回值可以用作 while 循环的条件。
仅当在 PHP 中启用 Solid 支持时,此函数才可用。
Solid_FieldName 函数将返回在给定的 Solid 结果标识符中占据给定列号的字段名称。字段编号从 0 开始。
仅当在 PHP 中启用 Solid 支持时,此函数才可用。
Solid_FieldNum 函数将返回与给定 Solid 结果标识符中命名的字段对应的列号。字段编号从 0 开始。此函数在出错时将返回 -1。
仅当在 PHP 中启用 Solid 支持时,此函数才可用。
只有当您担心脚本运行时使用过多内存时,才需要调用 Solid_FreeResult 函数。脚本结束后,所有结果内存都将自动释放。但是,如果您确定在脚本中不再需要结果数据,则可以使用结果标识符作为参数调用 Solid_FreeResult 函数,并释放关联的结果内存。
仅当在 PHP 中启用 Solid 支持时,此函数才可用。
Solid_NumFields 函数将返回 Solid 结果中的字段数(列数)。参数是由 Solid_Exec 返回的有效结果标识符。此函数在出错时将返回 -1。
仅当在 PHP 中启用 Solid 支持时,此函数才可用。
Solid_NumRows 函数将返回 Solid 结果中的行数。参数是由 Solid_Exec 返回的有效结果标识符。此函数在出错时将返回 -1。重大警告:SOLID SQL 服务器使用 ODBC 作为其主要(也是唯一)接口。SolidNumRows() 在底层使用 SQLRowCount 来获取行数。SQLRowCount 遵循微软由来已久的传统,即不必要的限制、奇怪的异常和其他奇怪的事情。这意味着该函数只返回 INSERT、UPDATE 或 DELETE 子句影响的行数。不包括 SELECT!作为解决方法,您可以尝试使用 SQL 的 count() 语句或计算行数的 while 循环。如果您需要 Solid_NumRows() 来确定在 SELECT 子句后读取多少条记录,请尝试检查 Solid_FetchRow() 的返回值。
$num = Solid_NumRows(); $i=0; while ($i < $num) { /* print results... */ $i++; }
您可以尝试
while(Solid_FetchRow($result)) { /* print results... */ }
仅当在 PHP 中启用 Solid 支持时,此函数才可用。
Solid_Result 函数将返回由 Solid_Exec 生成的结果标识符中的值。字段名称指定要返回的行中的哪个单元格。您可以使用字段索引作为无引号的数字来代替命名字段。字段索引从 0 开始。
仅当在 PHP 中启用 Solid 支持时,此函数才可用。
Sort 函数用于按升序对 PHP 数组进行排序。要按降序排序,请使用 RSort() 函数。它可以理解三种变量类型,如果数组包含字符串,则按字母顺序排序;如果数组包含数字,则按数字顺序排序。对于包含混合类型的数组,数组中的第一种类型将指定排序方法。请注意,如果您要排序关联数组,则应使用 ASort() 函数。
此函数接受一个字符串参数,并返回该字符串的 Soundex 编码。Soundex 编码具有这样的特性:发音相似的单词会产生相同的 Soundex 编码,因此可以用于简化数据库中的搜索,在这种情况下,您知道发音但不知道拼写。此 Soundex 函数返回一个 4 个字符长的字符串,以字母开头。
这个 Soundex 函数是由 Donald Knuth 在 "The Art Of Computer Programming, vol. 3: Sorting And Searching", Addison-Wesley (1973), pp. 391-392 中描述的。
示例
Euler and Ellery map to E460 Gauss and Ghosh map to G200 Hilbert and Heilbronn map to H416 Knuth and Kant map to K530 Lloyd and Ladd map to L300 Lukasiewicz and Lissajous map to L222
Sprintf 函数返回由 format 参数和 arg 定义的格式化输出创建的字符串。它类似于 echo 命令的格式化版本,区别在于它只返回字符串,而 echo 命令则显示它。它也类似于同名的 C 函数。区别在于此版本最多只接受 5 个 arg 参数。如果您需要将 5 个以上的参数格式化为单个字符串,只需多次调用 sprintf() 函数即可对每个参数组进行处理。请注意,参数的类型不会影响输出。参数类型会自动转换为与格式字符串中指定的类型匹配。
Sqrt 函数返回 arg 的平方根。
Srand 函数播种随机数生成器。此函数接受任何整数作为参数。一种种子值的选择是使用 date 函数为您提供当前经过的秒数。请注意,此函数不返回值!此函数只是为随后对 rand() 函数的调用播种随机数生成器。例如:
<?srand(date("s"))>
strchr 和 strstr 实际上是相同的函数。它们可以互换使用,并且都包含在内是为了完整起见。它们将返回从找到给定子字符串的位置开始的字符串参数的一部分。例如,在上例字符串 "This is an example string" 中,调用:<?echo strchr($string,"an ")>
将返回字符串:"an example string"
。
StripSlashes 函数取消转义字符串参数。另见 AddSlashes()。
strlen 函数返回字符串的长度。
strrchr 函数将从参数字符串的末尾开始搜索单个字符,并向后工作。如果找到该字符,则返回以搜索字符开头的字符串;如果没有找到,则返回空字符串。
strstr 和 strchr 实际上是相同的函数。它们可以互换使用,并且都包含在内是为了完整起见。它们将返回从找到给定子字符串的位置开始的字符串参数的一部分。例如,在上例字符串 "This is an example string" 中,调用:<?echo strstr($string,"an ")>
将返回字符串:"an example string"
。
strtok 函数用于将字符串标记化。也就是说,如果您有一个像 "This is an example string" 这样的字符串,您可以使用空格字符作为标记将其标记化为各个单词。您可以使用以下脚本代码
<? $string = "This is an example string"; $tok = strtok($string," "); while($tok); echo "Word=$tok<br>"; $tok = strtok(" "); endwhile; >
请注意,只有第一次调用 strtok 使用字符串参数。后续每次调用 strtok 只需要使用标记,因为它会跟踪它在当前字符串中的位置。要重新开始或标记化新的字符串,只需再次使用字符串参数调用 strtok 来初始化它即可。请注意,您可以在 arg 参数中放置多个标记。当找到参数中的任何一个字符时,字符串将被标记化。
strtolower 函数将字符串参数转换为全小写字符。
strtoupper 函数将字符串参数转换为全大写字符。
strval 函数返回变量的字符串值。另见 intval() 和 doubleval() 函数。
substr 函数返回给定字符串的一部分。起始位置由 start 参数给出。字符串中的第一个位置是位置 0。length 参数指定从起始位置返回的字符数。
如果已建立与数据库的连接,此函数返回 1;否则返回 0。
此函数为指定的数据库发出 Sybase Transact-SQL use 命令。此函数的唯一参数是要使用的数据库的名称。示例:sybsql_dbuse("pubs2");
成功时返回 1,失败时返回 0。
此函数打开与 Sybase 服务器的网络连接。此函数依赖于几个环境变量,调用者必须在调用此函数之前设置这些环境变量。
环境变量为:
DSQUERY - 在 Sybase 接口文件中定义的 Sybase 服务器的别名。
DBUSER - 以此用户身份连接到 Sybase 服务器。
DBPW - 用户的密码。
这些变量可以通过多种方式设置。如果 php/fi 作为 CGI 程序运行,则可以使用 shell 包装器来设置这些变量,或者您可以使用内置 PHP/FI 函数 putenv() 直接在 HTML 页面中设置这些变量。您可以从表单输入中获取值,而不是直接在 putenv() 中使用值。这些变量可以定义在一个文件中,并使用 PHP/FI 的 include
语句包含在 HTML 文件中。
成功时返回 1,失败时返回 0。
此函数强制关闭 Sybase 连接。如果没有调用此函数,则在 PHP 页面完全解析后,连接将自动关闭,因此调用此函数是可选的。
此函数返回常规结果列的字段名称。此函数的参数是字段索引。示例:sybsql_fieldname(0);
。注意:字段索引从 0 开始。
如果结果列没有任何名称,则该函数返回空字符串 ("")。
此函数获取当前结果行中特定列的值。函数的唯一参数是指定字段的字符串。例如:$value=sybsql_getfield("@10");
**注意**: 在调用此函数之前必须调用 sybsql_nextrow()。如果需要递增行指针,则必须调用 sybsql_nextrow(),因为此函数仅读取行缓冲区中的当前行。
如果指定的列有值,则函数将值作为字符串返回;否则,函数返回空字符串("")。
此函数指示当前 SQL 命令是否返回任何行。
如果 SQL 命令返回任何行,则函数返回 1;如果命令未返回任何行,则返回 0。
此函数将行指针递增到下一结果行。
只要还有剩余的行可读,函数就返回 1。如果没有更多行可读或发生错误,则函数返回 0。
此函数返回当前结果行中的字段数。
函数返回当前结果行中的行数。如果没有字段,则函数返回 0。
此函数返回当前结果缓冲区中的行数。**注意:** 调用此函数时,它会立即跳转到第一行,然后调用 dbnextrow() 直到没有更多行,并递增内部计数器以计算结果缓冲区中的行数。然后它指向第一行。因此,调用此函数后,行计数器始终指向第一行。这很不好,但我目前不知道其他方法。
如果结果缓冲区中没有行,则函数将返回 0。
此函数将 Sybase SQL 查询请求提交到服务器。函数的唯一参数是查询字符串。例如:$rc=sybsql_query("select * from authors");
如果查询成功,则函数返回 1;如果请求失败,则返回 0。
此函数打印当前结果行的特定字段。函数的唯一参数是一个字符串,其中包含有关要打印的字段的信息。字段由 @ 后跟一个数字指定。例如,@0 表示第一行,@10 表示第 11 行。请注意,字段编号从 0 开始。最好通过完整的示例来说明该函数。
<? /* ** assuming all the necessary variables for ** connection is already set. please note, NO error checking is ** done. You should always check return code of a function. */ /* connect */ $rc=sybsql_connect(); /* use the pub2 database */ $rc=sybsql_dbuse("pubs2"); /* send the SQL request */ $rc=sybsql_query("select * from authors"); $i=0; /* find the no of rows returned */ $nrows=sybsql_numrows(); /* start table */ echo "<table border>\n"; /* ** print only first and 2nd field */ while($i<$nrows) { sybsql_result("<tr><td>@0</td>@1</td></tr>\n"); $i++; } /* end table */ echo "</table>\n"; >
以上示例使用 HTML 表格来格式化输出。当然,可以使用任何其他有效的 HTML 标签。
此函数打印当前结果缓冲区中的所有行。结果以硬编码的 HTML 表格格式打印。请注意,不应在循环内调用此函数。如果输出中包含任何列标题,则该函数将打印列的名称。
此函数将请求的行号设置为行缓冲区中的当前行。函数的唯一参数是行号。例如:$rc=sybsql_seek(10);
请注意,行号从 0 开始。
如果查找成功,则函数返回 1;如果查找失败,则返回 0。当访问当前结果缓冲区中的所有行后,行指针指向最后一行。如果需要向后移动并访问更多行,则可以使用此函数。
Symlink() 创建符号链接。请参阅 Link() 函数以创建硬链接。
Syslog() 使用 UNIX 的 syslog(3) 功能将消息记录到系统。有关更多详细信息,请参见您的 UNIX 手册页。另请参见 InitSyslog()、OpenLog() 和 CloseLog()。
System 就像 C 的 system() 命令一样,它执行给定的 unix 命令并输出结果。如果将变量作为第二个参数提供,则执行的 unix 命令的返回状态代码将写入此变量。请注意,如果您要允许来自用户输入的数据传递到此 System 函数,则应使用 EscapeShellCmd() 函数,以确保用户无法欺骗系统执行任意命令。如果 PHP 作为 Apache 模块运行,则 System() 调用还会在每一行输出后自动刷新 Apache 输出缓冲区。如果您需要执行命令并将命令的所有数据直接传递回来而没有任何干扰,请使用 PassThru() 函数。另请参见 Exec 函数。
TempNam 返回位于 path 指定的目录中,文件名前缀为 prefix 的唯一文件名。它与 Unix C tempnam() 函数相同。
Time 简单地返回自 Unix 纪元 (00:00:00 1970 年 1 月 1 日) 以来以秒为单位的当前本地时间。它等效于调用 Date("U")。如果您需要比每秒更高的精度,请使用 Microtime 函数。
Umask(mask) 将 PHP 的 umask 设置为 mask & 0777 并返回旧的 umask。如果 PHP/FI 是 Apache 模块,则 PHP/FI 完成后将恢复 Apache 的旧 umask。mask 必须以 八进制 表示法指定,例如 ChMod()。不带参数的 Umask() 只返回当前的 umask。
UniqId 返回基于当前时间(以微秒为单位)的前缀唯一标识符。例如,如果您在可能碰巧在同一微秒生成标识符的多个主机上同时生成标识符,则前缀非常有用。前缀最多可以长达 114 个字符。
Unlink 删除给定的文件名。类似于 Unix C unlink() 函数。有关删除目录,请参见 RmDir() 函数。
UnSet 取消定义给定的变量。对于数组,将清除整个数组。也可以取消设置各个数组元素。
UrlDecode 解码使用 UrlEncode 函数编码的字符串。在典型用法中,不需要解码 URL 编码的字符串,因为这些字符串在页面之间传递时会自动解码。但是,为了完整起见,已包含此函数。
UrlEncode 对 arg 中不是 "a-zA-Z0-9_-." 之一的任何字符进行编码,方法是用 %xx 替换它们,其中 xx 是它们的十六进制 ASCII 值。返回编码后的字符串。
Sleep 将延迟给定的微秒数。类似于 Unix C usleep() 函数。另请参见 Sleep() 函数。
Virtual 是一个 Apache 特定的函数,它等效于 mod_include 中的 <!--#include virtual...-->。它执行 Apache 子请求。它可用于包含 CGI 脚本或 .shtml 文件,或您要通过 Apache 解析的任何其他内容(对于 .phtml 文件,您可能想要使用 <?Include>)。
在开始修改 PHP/FI 的内部结构之前,您需要获取最新版本的 Bison。Bison 是 GNU 的 YACC(Yet Another Compiler Compiler)的实现。您的操作系统附带的 YACC 可能足够好,也可能不够好,但为了确保,请获取 Bison。您可以在 ftp://prep.ai.mit.edu/pub/gnu 找到它。
您还应该查看 Makefile 并启用调试。只需取消 Makefile 中的 **DEBUG** 行的注释即可。调试信息的输出文件由 php.h 中的 **DEBUG_FILE** 指定。默认情况下,它设置为 /tmp/php.err。您可以根据需要更改它。
您可能还想记住的最后一件事是,php 以与系统上的 httpd 相同的用户 ID 运行,除非您当然是用 setuid 位设置运行它,而此 httpd 用户通常没有对各个目录的写入访问权限。这意味着,如果您执行导致 php 核心转储的操作,您将不会获得核心文件。解决此问题的简单方法是使您保存测试 .html 文件的目录对所有人可写。PHP 会将其当前目录更改为正在读取的 .html 文件的目录,如果可以,则会在那里转储其核心文件。
在以下步骤中,我们将使用 Time() 函数来说明如何添加函数。
如果您的函数最多接受 6 个参数,则可以使用预定义的语法。您可以跳过此步骤。
您的函数的语法在 parse.raw 文件中定义。首先要添加一个标记。标记是一个大写关键字,通常与您的函数名相同。所有标记都在 parse.raw 文件顶部附近定义。顺序无关紧要。然后,您需要构建实际的 YACC 语法规则。查看现有规则,找到与您要添加的规则相似的函数。请记住,大多数普通函数是标准函数,它们从表达式堆栈读取其参数。您的函数很可能属于此组,在这种情况下,您无需触摸 parse.raw 文件。
为此,请编辑 lex.c 并找到文件顶部的哈希表。查找定义哈希表开头的行 static cmd_table_t cmd_table[22][30] = {
。[22][30]
定义保存哈希表的二维数组的大小。22 比最大函数名长度大 1,30 指的是任何一个哈希列表中的最大函数数。如果超过这两个限制中的任何一个,只需在这里增加它们即可。
此哈希表可能被评为全世界最简单的哈希表。哈希值是要哈希的函数名字符串的长度。因此,对于我们的 Time() 示例,我们需要为哈希值 4 添加一个条目。因此,我们向 4 的哈希列表添加以下行:
{ "time",INTFUNC0,UnixTime },
此条目将字符串映射到 INTFUNC0 标记。您可以在 parse.raw 中查找 INTFUNC0 标记的语法,您将看到它是一个具有 0 个参数的内部函数调用的通用语法。上面的引号中的字符串是您将在 .html 文件中用于调用函数的实际字符串。请记住,PHP/FI 函数名称**不**区分大小写。最后的 **UnixTime** 元素是要调用的实际函数。
您实际上可以使用任何您喜欢的语言编写函数,只要它可以通过正常的 C 函数调用约定调用,并且您可以创建与系统上的链接器兼容的对象文件或库文件即可。一般来说,我们将假设您正在 C 中编写函数。PHP/FI 附带的所有函数都在 C 中编写。Time() 函数(在 PHP 内部称为 UnixTime())可以在 date.c 中找到,如下所示:
void UnixTime(void) { char temp[32]; sprintf(temp,"%ld",(long)time(NULL)); Push(temp,LNUMBER); }
请注意,该函数是 void 类型。这意味着它不返回任何值。这可能令您感到困惑,因为显然该函数需要以某种方式返回时间。时间确实被返回了,但不是作为函数的返回值。它被推送到所谓的表达式栈上。表达式栈只是一个字符串栈及其关联的类型。PHP/FI 只理解 3 种基本变量类型:STRING、LNUMBER 和 DNUMBER。STRING 是字符串,LNUMBER 是长整数,DNUMBER 是双精度浮点数。在这个 Time() 示例中,要返回的值是以 Unix 格式表示的时间(自 1970 年 1 月 1 日以来的秒数),因此是一个整数。表达式栈只接受字符串,因此我们将长整数使用 sprintf 格式化为字符串,并将其推送到栈上,并指示它实际上是一个长整数,代码如下:Push(temp,LNUMBER);
在 php.h 文件的下半部分,您会找到 PHP 中所有函数原型的完整列表。它们按其所在的源文件分组。只需将您的原型添加到此文件中的适当位置即可。对于我们的 Time() 示例,添加以下行:
void UnixTime(void);
每当您更改 parse.raw 文件时,都必须重新生成解析器。键入:make parser 来执行此操作。您必须至少拥有 1.25 版本的 Bison 才能生成 PHP 解析器。然后,完成此操作后,通过键入:make 进行常规编译。
如果您希望将您的函数添加到下一个 PHP/FI 版本中,请将其发送给我。最好的方法可能是创建一个上下文相关的差异文件。为此,您需要一份干净的未修改发行版的副本。只需对您已更改的文件执行 diff -c 命令,将其与原始文件进行比较即可。请不要向我发送 parse.c 中更改的差异,因为该文件是自动生成的。请改而发送 parse.raw 的差异。
Time() 示例说明了添加函数所涉及的步骤。您希望添加的函数很可能比此示例复杂得多。您可能希望能够向您的函数传递参数,并以某种方式操作这些参数。您甚至可能希望以不同的方式调用它。这些概念将通过 PHP/FI crypt() 函数来说明。另请参见标题为 代码修改说明 的部分,了解有关为 PHP/FI 编写代码的更多技术细节。
parse.raw 中的 Crypt() 语法
%token CRYPT . . . | CRYPT '(' expr ',' expr ')' { if(GetCurrentState(NULL) || inCase || inElseIf) Crypt(1); } | CRYPT '(' expr ')' { if(GetCurrentState(NULL) || inCase || inElseIf) Crypt(0); }
此处显示如何定义一个语法,该语法允许您使用 1 个或 2 个参数调用函数。您可以编写不同的函数来处理这两种情况,或者像这里一样简单地发送一个模式参数来指示调用函数的模式。请注意,在这种情况下,您不能使用预定义的 INTFUNCn 语法,因为您的函数可以接受可变数量的参数。
另一个方面是说明如何实际表示函数参数。在大多数情况下,您需要使用 expr 标识符。此标识符意味着参数是一个表达式。表达式可以是字面值、函数调用或许多表达式的组合。有关表达式的完整 yacc 语法定义,请参阅 parse.raw 以了解更多详细信息。
lex.c 中的哈希表条目
{ "crypt",CRYPT,NULL },
请注意,在这种情况下,最后一项是 NULL,因为函数调用直接在 parse.raw 中处理。如果您使用了 INTFUNCn 语法,则您将在此 NULL 的位置放置您的函数名称。crypt.c 中的实际 Crypt() 函数
/* * If mode is non-zero, a salt is expected. * If mode is zero, a pseudo-random salt will be selected. */ void Crypt(int mode) { #if HAVE_CRYPT Stack *s; char salt[8]; char *enc; salt[0] = '\0'; if(mode) { s = Pop(); if(!s) { Error("Stack error in crypt"); return; } if(s->strval) strncpy(salt,s->strval,2); } s = Pop(); if(!s) { Error("Stack error in crypt"); return; } if(!salt[0]) { salt[0] = 'A' + (time(NULL) % 26); salt[1] = 'a' + (time(NULL) % 26); salt[2] = '\0'; } enc = (char *)crypt(s->strval,salt); #if DEBUG Debug("Crypt returned [%s]\n",enc); #endif Push(enc,STRING); #else Error("No crypt support compiled into this version"); #endif }
此函数最重要的方面是 s = Pop() 调用。必须逐个将函数的参数从表达式栈中弹出。当您编写一个接受多个参数的函数时,请记住栈是一种后进先出 (LIFO) 数据结构。这意味着您将按相反的顺序从栈中弹出参数。最后一个参数先弹出。在上面的示例中,我们检查是否处于 2 个参数模式。如果处于 2 个参数模式,我们将参数从栈中弹出并保存它。然后,我们将下一个参数从栈中弹出。Pop() 返回指向 Stack 结构 (s) 的指针。Stack 结构如下所示(来自 php.h):
/* Expression Stack */ typedef struct Stack { short type; unsigned char *strval; long intval; double douval; VarTree *var; struct Stack *next; } Stack;
type 通常是 STRING、LNUMBER 或 DNUMBER 之一。strval、intval 和 douval 分量分别是值的字符串、整数和双精度表示。如果表达式实际上是一个已定义的变量,则 var 分量包含指向定义此变量的变量结构的指针。
在我们的 Crypt() 函数中,我们只对参数的字符串值感兴趣,因此我们使用 s->strval。许多 PHP/FI 函数可以通过检查 s->type 并适当地使用 s->strval、s->intval 和/或 s->douval 来执行不同的操作,具体取决于变量的类型。
调用真正的 crypt() 函数并获得加密字符串后,我们的 Crypt() 函数调用 Push(enc,STRING); 将返回值推送到表达式栈上。需要注意的是,表达式栈在每一行 PHP/FI 代码执行后都会被清除,因此如果您将永远不会被任何内容弹出的表达式推送到此栈上,则不会有任何影响。
Crypt() 示例中的 Debug() 调用显示了如何向您的函数添加调试输出。Debug() 是一个可变参数 (varargs) 函数,就像 printf 一样。
PHP/FI 中的内存管理是一件棘手的事情。由于我们可以作为服务器模块运行,因此我们必须非常小心地处理内存资源。我们不仅需要可重入,还需要处理这样一个事实:我们随时可能收到超时信号,此时我们会退出模块。我们不会收到任何警告,也没有时间释放我们可能已分配的任何内存。并且必须释放这部分内存,否则我们链接到的 httpd 进程的数据空间可能会无限增长。当 PHP 以 CGI 模式运行时,这也适用,因为它可以设置为以 FastCGI 持久进程运行。
解决方案是使用内存子池。这些池在会话终止时由 Apache 自动清除,或者在 FastCGI 持久进程的情况下,这些池在每次 FastCGI 包装器循环执行时在 main.c 中清除。
使用子池完全消除了在代码中的任何位置显式释放内存的需要,只有一个例外,即使用常规 malloc 调用由可能链接到 PHP 的各种库分配的内存。gdbm 库就是一个这样的例子。